remove unnecessary trait

This commit is contained in:
Manuel Gugger 2023-06-27 13:05:44 +02:00
parent 1ce89ed65c
commit a5ebc202e5
16 changed files with 170 additions and 256 deletions

View File

@ -24,7 +24,10 @@ pub struct Model {
pub comment: String pub comment: String
} }
// Custom Validation Functions
impl ActixAdminModelValidationTrait<ActiveModel> for Entity {} impl ActixAdminModelValidationTrait<ActiveModel> for Entity {}
// Custom Search Filters
impl ActixAdminModelFilterTrait<Entity> for Entity {}
``` ```
## Derive Implementations ## Derive Implementations
@ -65,7 +68,7 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
let mut admin_builder = ActixAdminBuilder::new(configuration); let mut admin_builder = ActixAdminBuilder::new(configuration);
let comment_view_model = ActixAdminViewModel::from(Comment); let comment_view_model = ActixAdminViewModel::from(Comment);
admin_builder.add_entity::<AppState, Comment>(&comment_view_model); admin_builder.add_entity::<Comment>(&comment_view_model);
admin_builder admin_builder
} }
@ -75,8 +78,8 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
Views / Models can be grouped in the Navbar by using the following functions instead of ```admin_builder.add_entity```: Views / Models can be grouped in the Navbar by using the following functions instead of ```admin_builder.add_entity```:
```rust ```rust
admin_builder.add_entity::<AppState, Comment>(&comment_view_model); admin_builder.add_entity::<Comment>(&comment_view_model);
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, "Group 1"); admin_builder.add_entity_to_category::<Comment>(&comment_view_model, "Group 1");
``` ```
## Additional Model Attributes ## Additional Model Attributes

View File

@ -22,16 +22,16 @@ A custom *custom_index.html* view can be defined as follows by extending the bas
To display the *custom_index.html*, define the corresponding function which extends the current tera context from actix-admin and also uses the actix-admin tera instance to render the custom index function. To display the *custom_index.html*, define the corresponding function which extends the current tera context from actix-admin and also uses the actix-admin tera instance to render the custom index function.
```rust ```rust
async fn custom_index<T: ActixAdminAppDataTrait + AppDataTrait>( async fn custom_index(
session: Session, session: Session,
data: web::Data<T> data: web::Data<AppState>
actix_admin: web::Data<ActixAdmin>
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.extend(get_admin_ctx(session, &data)); ctx.extend(get_admin_ctx(session, &actix_admin));
let body = data.get_tmpl() let body = data.tmpl.render("custom_index.html", &ctx).unwrap();
.render("custom_index.html", &ctx).unwrap();
Ok(HttpResponse::Ok().content_type("text/html").body(body)) Ok(HttpResponse::Ok().content_type("text/html").body(body))
} }
@ -40,8 +40,8 @@ async fn custom_index<T: ActixAdminAppDataTrait + AppDataTrait>(
After this in the builder, pass your custom index function defined above: After this in the builder, pass your custom index function defined above:
```rust ```rust
let mut admin_builder = ActixAdminBuilder::new(configuration); let mut admin_builder = ActixAdminBuilder::new(configuration);
admin_builder.add_custom_handler_for_index::<AppState>( admin_builder.add_custom_handler_for_index(
web::get().to(custom_index::<AppState>) web::get().to(custom_index)
); );
``` ```
@ -53,7 +53,7 @@ Similarly to the custom index above, the builder accepts additional routes to be
```rust ```rust
// This will be shown in the top level menu // This will be shown in the top level menu
let show_in_menu = true; let show_in_menu = true;
admin_builder.add_custom_handler("Custom Route in Menu", "/custom_route_in_menu", web::get().to custom_index::<AppState>), show_in_menu); admin_builder.add_custom_handler("Custom Route in Menu", "/custom_route_in_menu", web::get().to(custom_index), show_in_menu);
``` ```
### Tied to a specific entity ### Tied to a specific entity
@ -61,11 +61,11 @@ admin_builder.add_custom_handler("Custom Route in Menu", "/custom_route_in_menu"
// this will expose a menu item which links to /admin/comment/custom_handler and is shown in the NavBar menu // this will expose a menu item which links to /admin/comment/custom_handler and is shown in the NavBar menu
let show_in_menu = true; let show_in_menu = true;
let some_category = "Some Category"; let some_category = "Some Category";
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category); admin_builder.add_entity_to_category::<Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity::<AppState, Comment>( admin_builder.add_custom_handler_for_entity::<Comment>(
"My custom handler", "My custom handler",
"/custom_handler", "/custom_handler",
web::get().to(custom_handler::<AppState, Comment>), web::get().to(custom_handler::<Comment>),
show_in_menu show_in_menu
); );
``` ```
@ -75,11 +75,11 @@ admin_builder.add_custom_handler_for_entity::<AppState, Comment>(
// this will expose a menu item which links to /admin/comment/custom_handler and is shown in the NavBar menu in the group "Some Category" // this will expose a menu item which links to /admin/comment/custom_handler and is shown in the NavBar menu in the group "Some Category"
let show_in_menu = true; let show_in_menu = true;
let some_category = "Some Category"; let some_category = "Some Category";
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category); admin_builder.add_entity_to_category::<Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity_in_category::<AppState, Comment>( admin_builder.add_custom_handler_for_entity_in_category::<Comment>(
"My custom handler", "My custom handler",
"/custom_handler", "/custom_handler",
web::get().to(custom_handler::<AppState, Comment>), web::get().to(custom_handler::<Comment>),
some_category, some_category,
show_in_menu show_in_menu
); );

View File

@ -12,30 +12,7 @@ weight: 1
Cargo.toml: Cargo.toml:
```cargo ```cargo
[dependencies] [dependencies]
actix-admin = "0.3.0" actix-admin = "0.4.0"
```
## Implement the Trait for AppState
Actix-Admin requires to get the database connection and its configuration from the actix AppState. The trait "ActixAdminAppDataTrait" must be implemented for your AppState:
```rust
use actix_admin::prelude::*;
#[derive(Clone)]
pub struct AppState {
pub db: DatabaseConnection,
pub actix_admin: ActixAdmin,
}
impl ActixAdminAppDataTrait for AppState {
fn get_db(&self) -> &DatabaseConnection {
&self.db
}
fn get_actix_admin(&self) -> &ActixAdmin {
&self.actix_admin
}
}
``` ```
## Build the Actix-Admin Configuration ## Build the Actix-Admin Configuration
@ -65,15 +42,13 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
The AppState and the configuration can be passed to Actix-Web like in the following snippet. The ActixAdminBuilder creates an own */admin/* Scope which is registered as a service in the Actix-Web app. The AppState and the configuration can be passed to Actix-Web like in the following snippet. The ActixAdminBuilder creates an own */admin/* Scope which is registered as a service in the Actix-Web app.
```rust ```rust
let conn = sea_orm::Database::connect(opt).await.unwrap();
let actix_admin_builder = create_actix_admin_builder(); let actix_admin_builder = create_actix_admin_builder();
let app_state = AppState {
db: conn.clone(),
actix_admin: actix_admin_builder.get_actix_admin(),
};
let app = App::new() let app = App::new()
.app_data(web::Data::new(app_state)) .app_data(web::Data::new(app_state))
.app_data(web::Data::new(conn.clone()))
.app_data(web::Data::new(actix_admin_builder.get_actix_admin()))
.service( .service(
actix_admin_builder.get_scope::<AppState>() actix_admin_builder.get_scope::<AppState>()
) )

View File

@ -6,7 +6,7 @@ use actix_web::{cookie::Key, web, App, HttpResponse, HttpServer, middleware};
use azure_auth::{AppDataTrait as AzureAuthAppDataTrait, AzureAuth, UserInfo}; use azure_auth::{AppDataTrait as AzureAuthAppDataTrait, AzureAuth, UserInfo};
use oauth2::basic::BasicClient; use oauth2::basic::BasicClient;
use oauth2::RedirectUrl; use oauth2::RedirectUrl;
use sea_orm::{ConnectOptions, DatabaseConnection}; use sea_orm::{ConnectOptions};
use std::env; use std::env;
use std::time::Duration; use std::time::Duration;
use tera::{Context, Tera}; use tera::{Context, Tera};
@ -18,28 +18,7 @@ use entity::{Post, Comment};
#[derive(Clone)] #[derive(Clone)]
pub struct AppState { pub struct AppState {
pub oauth: BasicClient, pub oauth: BasicClient,
pub tmpl: Tera, pub tmpl: Tera
pub db: DatabaseConnection,
pub actix_admin: ActixAdmin,
}
impl ActixAdminAppDataTrait for AppState {
fn get_db(&self) -> &DatabaseConnection {
&self.db
}
fn get_actix_admin(&self) -> &ActixAdmin {
&self.actix_admin
}
}
trait AppDataTrait {
fn get_tmpl(&self) -> &Tera;
}
impl AppDataTrait for AppState {
fn get_tmpl(&self) -> &Tera {
&self.tmpl
}
} }
impl AzureAuthAppDataTrait for AppState { impl AzureAuthAppDataTrait for AppState {
@ -48,42 +27,36 @@ impl AzureAuthAppDataTrait for AppState {
} }
} }
async fn custom_handler< async fn custom_handler(
T: ActixAdminAppDataTrait + AppDataTrait,
E: ActixAdminViewModelTrait,
>(
session: Session, session: Session,
data: web::Data<T>, data: web::Data<AppState>,
actix_admin: web::Data<ActixAdmin>,
_text: String _text: String
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.extend(get_admin_ctx(session, &data)); ctx.extend(get_admin_ctx(session, &actix_admin));
let body = data.get_tmpl() let body = data.tmpl.render("custom_handler.html", &ctx).unwrap();
.render("custom_handler.html", &ctx).unwrap();
Ok(HttpResponse::Ok().content_type("text/html").body(body)) Ok(HttpResponse::Ok().content_type("text/html").body(body))
} }
async fn custom_index< async fn custom_index(
T: ActixAdminAppDataTrait + AppDataTrait
>(
session: Session, session: Session,
data: web::Data<T>, data: web::Data<AppState>,
actix_admin: web::Data<ActixAdmin>,
_text: String _text: String
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.extend(get_admin_ctx(session, &data)); ctx.extend(get_admin_ctx(session, &actix_admin));
let body = data.get_tmpl() let body = data.tmpl.render("custom_index.html", &ctx).unwrap();
.render("custom_index.html", &ctx).unwrap();
Ok(HttpResponse::Ok().content_type("text/html").body(body)) Ok(HttpResponse::Ok().content_type("text/html").body(body))
} }
async fn index(session: Session, data: web::Data<AppState>) -> HttpResponse { async fn index(session: Session, data: web::Data<AppState>) -> HttpResponse {
let login = session.get::<UserInfo>("user_info").unwrap(); let login = session.get::<UserInfo>("user_info").unwrap();
let web_auth_link = if login.is_some() { let web_auth_link = if login.is_some() {
@ -115,19 +88,19 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
}; };
let mut admin_builder = ActixAdminBuilder::new(configuration); let mut admin_builder = ActixAdminBuilder::new(configuration);
admin_builder.add_custom_handler_for_index::<AppState>( admin_builder.add_custom_handler_for_index(
web::get().to(custom_index::<AppState>) web::get().to(custom_index)
); );
admin_builder.add_entity::<AppState, Post>(&post_view_model); admin_builder.add_entity::<Post>(&post_view_model);
admin_builder.add_custom_handler("Custom Route in Menu", "/custom_route_in_menu", web::get().to(custom_index::<AppState>), true); admin_builder.add_custom_handler("Custom Route in Menu", "/custom_route_in_menu", web::get().to(custom_index), true);
admin_builder.add_custom_handler("Custom Route not in Menu", "/custom_route_not_in_menu", web::get().to(custom_index::<AppState>), false); admin_builder.add_custom_handler("Custom Route not in Menu", "/custom_route_not_in_menu", web::get().to(custom_index), false);
let some_category = "Some Category"; let some_category = "Some Category";
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category); admin_builder.add_entity_to_category::<Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity_in_category::<AppState, Comment>( admin_builder.add_custom_handler_for_entity_in_category::<Comment>(
"My custom handler", "My custom handler",
"/custom_handler", "/custom_handler",
web::get().to(custom_handler::<AppState, Comment>), web::get().to(custom_handler),
some_category, some_category,
true true
); );
@ -179,18 +152,18 @@ async fn main() {
let app_state = AppState { let app_state = AppState {
oauth: client.clone(), oauth: client.clone(),
tmpl: tera.clone(), tmpl: tera.clone()
db: conn.clone(),
actix_admin: actix_admin,
}; };
App::new() App::new()
.app_data(web::Data::new(app_state.clone())) .app_data(web::Data::new(app_state.clone()))
.app_data(web::Data::new(conn.clone()))
.app_data(web::Data::new(actix_admin.clone()))
.wrap(SessionMiddleware::new(CookieSessionStore::default(), cookie_secret_key.clone())) .wrap(SessionMiddleware::new(CookieSessionStore::default(), cookie_secret_key.clone()))
.route("/", web::get().to(index)) .route("/", web::get().to(index))
.service(azure_auth.clone().create_scope::<AppState>()) .service(azure_auth.clone().create_scope::<AppState>())
.service( .service(
actix_admin_builder.get_scope::<AppState>() actix_admin_builder.get_scope()
) )
.wrap(middleware::Logger::default()) .wrap(middleware::Logger::default())
}) })

View File

@ -2,26 +2,11 @@ extern crate serde_derive;
use actix_admin::prelude::*; use actix_admin::prelude::*;
use actix_web::{web, App, HttpServer, middleware}; use actix_web::{web, App, HttpServer, middleware};
use sea_orm::{ConnectOptions, DatabaseConnection}; use sea_orm::{ConnectOptions};
use std::time::Duration; use std::time::Duration;
mod entity; mod entity;
use entity::{Post, Comment, User}; use entity::{Post, Comment, User};
#[derive(Clone)]
pub struct AppState {
pub db: DatabaseConnection,
pub actix_admin: ActixAdmin,
}
impl ActixAdminAppDataTrait for AppState {
fn get_db(&self) -> &DatabaseConnection {
&self.db
}
fn get_actix_admin(&self) -> &ActixAdmin {
&self.actix_admin
}
}
fn create_actix_admin_builder() -> ActixAdminBuilder { fn create_actix_admin_builder() -> ActixAdminBuilder {
let configuration = ActixAdminConfiguration { let configuration = ActixAdminConfiguration {
enable_auth: false, enable_auth: false,
@ -35,13 +20,13 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
let mut admin_builder = ActixAdminBuilder::new(configuration); let mut admin_builder = ActixAdminBuilder::new(configuration);
let post_view_model = ActixAdminViewModel::from(Post); let post_view_model = ActixAdminViewModel::from(Post);
admin_builder.add_entity::<AppState, Post>(&post_view_model); admin_builder.add_entity::<Post>(&post_view_model);
let some_category = "Group"; let some_category = "Group";
let comment_view_model = ActixAdminViewModel::from(Comment); let comment_view_model = ActixAdminViewModel::from(Comment);
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category); admin_builder.add_entity_to_category::<Comment>(&comment_view_model, some_category);
let user_view_model = ActixAdminViewModel::from(User); let user_view_model = ActixAdminViewModel::from(User);
admin_builder.add_entity_to_category::<AppState, User>(&user_view_model, some_category); admin_builder.add_entity_to_category::<User>(&user_view_model, some_category);
admin_builder admin_builder
} }
@ -60,7 +45,7 @@ fn get_db_options() -> ConnectOptions {
#[actix_rt::main] #[actix_rt::main]
async fn main() { async fn main() {
let opt = get_db_options(); let opt = get_db_options();
let conn = sea_orm::Database::connect(opt).await.unwrap(); let conn: sea_orm::DatabaseConnection = sea_orm::Database::connect(opt).await.unwrap();
let _ = entity::create_post_table(&conn).await; let _ = entity::create_post_table(&conn).await;
println!("The admin interface is available at http://localhost:5000/admin/"); println!("The admin interface is available at http://localhost:5000/admin/");
@ -69,15 +54,11 @@ async fn main() {
let actix_admin_builder = create_actix_admin_builder(); let actix_admin_builder = create_actix_admin_builder();
let app_state = AppState {
db: conn.clone(),
actix_admin: actix_admin_builder.get_actix_admin(),
};
App::new() App::new()
.app_data(web::Data::new(app_state)) .app_data(web::Data::new(actix_admin_builder.get_actix_admin()))
.app_data(web::Data::new(conn.clone()))
.service( .service(
actix_admin_builder.get_scope::<AppState>() actix_admin_builder.get_scope()
) )
.wrap(middleware::Logger::default()) .wrap(middleware::Logger::default())
}) })

View File

@ -20,12 +20,11 @@ pub struct ActixAdminBuilder {
/// The trait to work with ActixAdminBuilder /// The trait to work with ActixAdminBuilder
pub trait ActixAdminBuilderTrait { pub trait ActixAdminBuilderTrait {
fn new(configuration: ActixAdminConfiguration) -> Self; fn new(configuration: ActixAdminConfiguration) -> Self;
fn add_entity<T: ActixAdminAppDataTrait + 'static, E: ActixAdminViewModelTrait + 'static>( fn add_entity<E: ActixAdminViewModelTrait + 'static>(
&mut self, &mut self,
view_model: &ActixAdminViewModel, view_model: &ActixAdminViewModel,
); );
fn add_entity_to_category< fn add_entity_to_category<
T: ActixAdminAppDataTrait + 'static,
E: ActixAdminViewModelTrait + 'static, E: ActixAdminViewModelTrait + 'static,
>( >(
&mut self, &mut self,
@ -40,7 +39,6 @@ pub trait ActixAdminBuilderTrait {
add_to_menu: bool, add_to_menu: bool,
); );
fn add_custom_handler_for_entity< fn add_custom_handler_for_entity<
T: ActixAdminAppDataTrait + 'static,
E: ActixAdminViewModelTrait + 'static, E: ActixAdminViewModelTrait + 'static,
>( >(
&mut self, &mut self,
@ -50,7 +48,6 @@ pub trait ActixAdminBuilderTrait {
add_to_menu: bool add_to_menu: bool
); );
fn add_custom_handler_for_entity_in_category< fn add_custom_handler_for_entity_in_category<
T: ActixAdminAppDataTrait + 'static,
E: ActixAdminViewModelTrait + 'static, E: ActixAdminViewModelTrait + 'static,
>( >(
&mut self, &mut self,
@ -60,8 +57,8 @@ pub trait ActixAdminBuilderTrait {
category_name: &str, category_name: &str,
add_to_menu: bool, add_to_menu: bool,
); );
fn add_custom_handler_for_index<T: ActixAdminAppDataTrait + 'static>(&mut self, route: Route); fn add_custom_handler_for_index(&mut self, route: Route);
fn get_scope<T: ActixAdminAppDataTrait + 'static>(self) -> actix_web::Scope; fn get_scope(self) -> actix_web::Scope;
fn get_actix_admin(&self) -> ActixAdmin; fn get_actix_admin(&self) -> ActixAdmin;
} }
@ -207,15 +204,14 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
} }
} }
fn add_entity<T: ActixAdminAppDataTrait + 'static, E: ActixAdminViewModelTrait + 'static>( fn add_entity<E: ActixAdminViewModelTrait + 'static>(
&mut self, &mut self,
view_model: &ActixAdminViewModel, view_model: &ActixAdminViewModel,
) { ) {
let _ = &self.add_entity_to_category::<T, E>(view_model, ""); let _ = &self.add_entity_to_category::<E>(view_model, "");
} }
fn add_entity_to_category< fn add_entity_to_category<
T: ActixAdminAppDataTrait + 'static,
E: ActixAdminViewModelTrait + 'static, E: ActixAdminViewModelTrait + 'static,
>( >(
&mut self, &mut self,
@ -225,17 +221,17 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
self.scopes.insert( self.scopes.insert(
E::get_entity_name(), E::get_entity_name(),
web::scope(&format!("/{}", E::get_entity_name())) web::scope(&format!("/{}", E::get_entity_name()))
.route("/list", web::get().to(list::<T, E>)) .route("/list", web::get().to(list::<E>))
.route("/create", web::get().to(create_get::<T, E>)) .route("/create", web::get().to(create_get::<E>))
.route("/create", web::post().to(create_post::<T, E>)) .route("/create", web::post().to(create_post::<E>))
.route("/edit/{id}", web::get().to(edit_get::<T, E>)) .route("/edit/{id}", web::get().to(edit_get::<E>))
.route("/edit/{id}", web::post().to(edit_post::<T, E>)) .route("/edit/{id}", web::post().to(edit_post::<E>))
.route("/delete", web::delete().to(delete_many::<T, E>)) .route("/delete", web::delete().to(delete_many::<E>))
.route("/delete/{id}", web::delete().to(delete::<T, E>)) .route("/delete/{id}", web::delete().to(delete::<E>))
.route("/show/{id}", web::get().to(show::<T, E>)) .route("/show/{id}", web::get().to(show::<E>))
.route("/file/{id}/{column_name}", web::get().to(download::<T, E>)) .route("/file/{id}/{column_name}", web::get().to(download::<E>))
.route("/file/{id}/{column_name}", web::delete().to(delete_file::<T, E>)) .route("/file/{id}/{column_name}", web::delete().to(delete_file::<E>))
.default_service(web::to(not_found::<T>)) .default_service(web::to(not_found))
); );
fs::create_dir_all(format!("{}/{}", &self.actix_admin.configuration.file_upload_directory, E::get_entity_name())).unwrap(); fs::create_dir_all(format!("{}/{}", &self.actix_admin.configuration.file_upload_directory, E::get_entity_name())).unwrap();
@ -261,7 +257,7 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
self.actix_admin.view_models.insert(key, view_model.clone()); self.actix_admin.view_models.insert(key, view_model.clone());
} }
fn add_custom_handler_for_index<T: ActixAdminAppDataTrait + 'static>(&mut self, route: Route) { fn add_custom_handler_for_index(&mut self, route: Route) {
self.custom_index = Some(route); self.custom_index = Some(route);
} }
@ -293,7 +289,6 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
} }
fn add_custom_handler_for_entity< fn add_custom_handler_for_entity<
T: ActixAdminAppDataTrait + 'static,
E: ActixAdminViewModelTrait + 'static, E: ActixAdminViewModelTrait + 'static,
>( >(
&mut self, &mut self,
@ -302,7 +297,7 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
route: Route, route: Route,
add_to_menu: bool, add_to_menu: bool,
) { ) {
let _ = &self.add_custom_handler_for_entity_in_category::<T, E>( let _ = &self.add_custom_handler_for_entity_in_category::<E>(
menu_element_name, menu_element_name,
path, path,
route, route,
@ -312,7 +307,6 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
} }
fn add_custom_handler_for_entity_in_category< fn add_custom_handler_for_entity_in_category<
T: ActixAdminAppDataTrait + 'static,
E: ActixAdminViewModelTrait + 'static, E: ActixAdminViewModelTrait + 'static,
>( >(
&mut self, &mut self,
@ -356,14 +350,14 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
} }
} }
fn get_scope<T: ActixAdminAppDataTrait + 'static>(self) -> actix_web::Scope { fn get_scope(self) -> actix_web::Scope {
let index_handler = match self.custom_index { let index_handler = match self.custom_index {
Some(handler) => handler, Some(handler) => handler,
_ => web::get().to(index::<T>), _ => web::get().to(index),
}; };
let mut admin_scope = web::scope("/admin") let mut admin_scope = web::scope("/admin")
.route("/", index_handler) .route("/", index_handler)
.default_service(web::to(not_found::<T>)); .default_service(web::to(not_found));
for (_entity, scope) in self.scopes { for (_entity, scope) in self.scopes {
admin_scope = admin_scope.service(scope); admin_scope = admin_scope.service(scope);

View File

@ -31,7 +31,7 @@ pub mod prelude {
ActixAdminViewModelSerializable, ActixAdminViewModelTrait, ActixAdminViewModelFilter ActixAdminViewModelSerializable, ActixAdminViewModelTrait, ActixAdminViewModelFilter
}; };
pub use crate::{hashmap, ActixAdminSelectListTrait}; pub use crate::{hashmap, ActixAdminSelectListTrait};
pub use crate::{ActixAdmin, ActixAdminAppDataTrait, ActixAdminConfiguration, ActixAdminError}; pub use crate::{ActixAdmin, ActixAdminConfiguration, ActixAdminError};
pub use actix_admin_macros::{ pub use actix_admin_macros::{
DeriveActixAdmin, DeriveActixAdminEnumSelectList, DeriveActixAdminModel, DeriveActixAdmin, DeriveActixAdminEnumSelectList, DeriveActixAdminModel,
DeriveActixAdminModelSelectList, DeriveActixAdminViewModel, DeriveActixAdminModelSelectList, DeriveActixAdminViewModel,
@ -53,12 +53,6 @@ macro_rules! hashmap {
}} }}
} }
// AppDataTrait
pub trait ActixAdminAppDataTrait {
fn get_db(&self) -> &DatabaseConnection;
fn get_actix_admin(&self) -> &ActixAdmin;
}
// SelectListTrait // SelectListTrait
#[async_trait] #[async_trait]
pub trait ActixAdminSelectListTrait { pub trait ActixAdminSelectListTrait {

View File

@ -1,4 +1,5 @@
use actix_web::{error, web, Error, HttpRequest, HttpResponse}; use actix_web::{error, web, Error, HttpRequest, HttpResponse};
use sea_orm::DatabaseConnection;
use tera::{Context}; use tera::{Context};
use actix_session::{Session}; use actix_session::{Session};
use crate::ActixAdminError; use crate::ActixAdminError;
@ -9,34 +10,36 @@ use super::DEFAULT_ENTITIES_PER_PAGE;
use super::Params; use super::Params;
use super::{ add_auth_context, user_can_access_page, render_unauthorized}; use super::{ add_auth_context, user_can_access_page, render_unauthorized};
pub async fn create_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( pub async fn create_get<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
req: HttpRequest, req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
_body: web::Payload, _body: web::Payload,
_text: String, _text: String,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let db = &data.get_db(); let db = db.get_ref();
let model = ActixAdminModel::create_empty(); let model = ActixAdminModel::create_empty();
create_or_edit_get::<T, E>(&session, req, &data, db, Ok(model)).await create_or_edit_get::<E>(&session, req, &data, db, Ok(model)).await
} }
pub async fn edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( pub async fn edit_get<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
req: HttpRequest, req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
_text: String, _text: String,
id: web::Path<i32> id: web::Path<i32>
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let db = &data.get_db(); let db = db.get_ref();
let model = E::get_entity(db, id.into_inner()).await; let model = E::get_entity(db, id.into_inner()).await;
create_or_edit_get::<T, E>(&session, req, &data, db, model).await create_or_edit_get::<E>(&session, req, &data, db, model).await
} }
async fn create_or_edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(session: &Session, req: HttpRequest, data: &web::Data<T>, db: &sea_orm::DatabaseConnection, model_result: Result<ActixAdminModel, ActixAdminError>) -> Result<HttpResponse, Error>{ async fn create_or_edit_get<E: ActixAdminViewModelTrait>(session: &Session, req: HttpRequest, data: &web::Data<ActixAdmin>, db: &sea_orm::DatabaseConnection, model_result: Result<ActixAdminModel, ActixAdminError>) -> Result<HttpResponse, Error>{
let actix_admin = &data.get_actix_admin(); let actix_admin = &data.get_ref();
let mut ctx = Context::new(); let mut ctx = Context::new();
add_auth_context(&session, actix_admin, &mut ctx); add_auth_context(&session, actix_admin, &mut ctx);
let entity_names = &actix_admin.entity_names; let entity_names = &actix_admin.entity_names;

View File

@ -8,16 +8,18 @@ use actix_multipart::MultipartError;
use actix_session::Session; use actix_session::Session;
use actix_web::http::header; use actix_web::http::header;
use actix_web::{error, web, Error, HttpRequest, HttpResponse}; use actix_web::{error, web, Error, HttpRequest, HttpResponse};
use sea_orm::DatabaseConnection;
use std::collections::HashMap; use std::collections::HashMap;
use tera::Context; use tera::Context;
pub async fn create_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( pub async fn create_post<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
req: HttpRequest, req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
payload: Multipart, payload: Multipart,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = data.get_ref();
let model = ActixAdminModel::create_from_payload( let model = ActixAdminModel::create_from_payload(
payload, payload,
&format!( &format!(
@ -27,17 +29,18 @@ pub async fn create_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>
), ),
) )
.await; .await;
create_or_edit_post::<T, E>(&session, req, &data, model, None, actix_admin).await create_or_edit_post::<E>(&session, req, db, model, None, actix_admin).await
} }
pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( pub async fn edit_post<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
req: HttpRequest, req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
payload: Multipart, payload: Multipart,
id: web::Path<i32>, id: web::Path<i32>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = &data.get_ref();
let model = ActixAdminModel::create_from_payload( let model = ActixAdminModel::create_from_payload(
payload, payload,
&format!( &format!(
@ -47,10 +50,10 @@ pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
), ),
) )
.await; .await;
create_or_edit_post::<T, E>( create_or_edit_post::<E>(
&session, &session,
req, req,
&data, db,
model, model,
Some(id.into_inner()), Some(id.into_inner()),
actix_admin, actix_admin,
@ -58,10 +61,10 @@ pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
.await .await
} }
pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( pub async fn create_or_edit_post<E: ActixAdminViewModelTrait>(
session: &Session, session: &Session,
req: HttpRequest, req: HttpRequest,
data: &web::Data<T>, db: web::Data<DatabaseConnection>,
model_res: Result<ActixAdminModel, MultipartError>, model_res: Result<ActixAdminModel, MultipartError>,
id: Option<i32>, id: Option<i32>,
actix_admin: &ActixAdmin, actix_admin: &ActixAdmin,
@ -76,7 +79,7 @@ pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewMod
ctx.insert("render_partial", &true); ctx.insert("render_partial", &true);
return render_unauthorized(&ctx, &actix_admin); return render_unauthorized(&ctx, &actix_admin);
} }
let db = &data.get_db(); let db = db.get_ref();
let mut model = model_res.unwrap(); let mut model = model_res.unwrap();
E::validate_entity(&mut model); E::validate_entity(&mut model);
@ -87,7 +90,7 @@ pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewMod
req, req,
actix_admin, actix_admin,
view_model, view_model,
db, &db,
entity_name, entity_name,
&model, &model,
errors, errors,
@ -127,7 +130,7 @@ pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewMod
req, req,
actix_admin, actix_admin,
view_model, view_model,
db, &db,
entity_name, entity_name,
&model, &model,
errors, errors,

View File

@ -3,16 +3,18 @@ use crate::prelude::*;
use actix_session::Session; use actix_session::Session;
use actix_web::http::header; use actix_web::http::header;
use actix_web::{web, Error, HttpRequest, HttpResponse}; use actix_web::{web, Error, HttpRequest, HttpResponse};
use sea_orm::DatabaseConnection;
use tera::Context; use tera::Context;
pub async fn delete<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( pub async fn delete<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
_req: HttpRequest, _req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
_text: String, _text: String,
id: web::Path<i32>, id: web::Path<i32>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = &data.into_inner();
let entity_name = E::get_entity_name(); let entity_name = E::get_entity_name();
let view_model = actix_admin.view_models.get(&entity_name).unwrap(); let view_model = actix_admin.view_models.get(&entity_name).unwrap();
@ -23,7 +25,7 @@ pub async fn delete<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
return render_unauthorized(&ctx, &actix_admin); return render_unauthorized(&ctx, &actix_admin);
} }
let db = &data.get_db(); let db = &db.get_ref();
let id = id.into_inner(); let id = id.into_inner();
let model_result = E::get_entity(db, id).await; let model_result = E::get_entity(db, id).await;
let delete_result = E::delete_entity(db, id).await; let delete_result = E::delete_entity(db, id).await;
@ -53,13 +55,14 @@ pub async fn delete<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
} }
} }
pub async fn delete_many<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( pub async fn delete_many<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
_req: HttpRequest, _req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
form: web::Form<Vec<(String, String)>>, form: web::Form<Vec<(String, String)>>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = data.get_ref();
let entity_name = E::get_entity_name(); let entity_name = E::get_entity_name();
let view_model = actix_admin.view_models.get(&entity_name).unwrap(); let view_model = actix_admin.view_models.get(&entity_name).unwrap();
@ -71,7 +74,7 @@ pub async fn delete_many<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>
return render_unauthorized(&ctx, &actix_admin); return render_unauthorized(&ctx, &actix_admin);
} }
let db = &data.get_db(); let db = &db.get_ref();
let entity_name = E::get_entity_name(); let entity_name = E::get_entity_name();
let ids: Vec<i32> = form.iter().filter(|el| el.0 == "ids").map(|el| el.1.parse::<i32>().unwrap()).collect(); let ids: Vec<i32> = form.iter().filter(|el| el.0 == "ids").map(|el| el.1.parse::<i32>().unwrap()).collect();

View File

@ -1,13 +1,14 @@
use actix_web::{web, error, Error, HttpResponse, HttpRequest}; use actix_web::{web, error, Error, HttpResponse, HttpRequest};
use actix_session::{Session}; use actix_session::{Session};
use sea_orm::DatabaseConnection;
use tera::{Context}; use tera::{Context};
use crate::prelude::*; use crate::prelude::*;
use super::{ user_can_access_page, render_unauthorized}; use super::{ user_can_access_page, render_unauthorized};
pub async fn download<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(req: HttpRequest, session: Session, data: web::Data<T>, params: web::Path<(i32, String)>) -> Result<HttpResponse, Error> { pub async fn download<E: ActixAdminViewModelTrait>(req: HttpRequest, session: Session, data: web::Data<ActixAdmin>, db: web::Data<DatabaseConnection>, params: web::Path<(i32, String)>) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = &data.into_inner();
let db = &data.get_db(); let db = &db.into_inner();
let ctx = Context::new(); let ctx = Context::new();
let entity_name = E::get_entity_name(); let entity_name = E::get_entity_name();
@ -41,9 +42,8 @@ pub async fn download<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(re
} }
pub async fn delete_file<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(session: Session, data: web::Data<T>, params: web::Path<(i32, String)>) -> Result<HttpResponse, Error> { pub async fn delete_file<E: ActixAdminViewModelTrait>(session: Session, data: web::Data<ActixAdmin>, db: web::Data<DatabaseConnection>, params: web::Path<(i32, String)>) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = &data.into_inner();
let db = &data.get_db();
let mut ctx = Context::new(); let mut ctx = Context::new();
let entity_name = E::get_entity_name(); let entity_name = E::get_entity_name();
@ -54,7 +54,7 @@ pub async fn delete_file<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>
let (id, column_name) = params.into_inner(); let (id, column_name) = params.into_inner();
let mut errors: Vec<crate::ActixAdminError> = Vec::new(); let mut errors: Vec<crate::ActixAdminError> = Vec::new();
let result = E::get_entity(db, id).await; let result = E::get_entity(db.get_ref(), id).await;
let mut model; let mut model;
match result { match result {
Ok(res) => { Ok(res) => {
@ -70,7 +70,7 @@ pub async fn delete_file<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>
let file_path = format!("{}/{}/{}", actix_admin.configuration.file_upload_directory, E::get_entity_name(), file_name.unwrap_or_default()); let file_path = format!("{}/{}/{}", actix_admin.configuration.file_upload_directory, E::get_entity_name(), file_name.unwrap_or_default());
std::fs::remove_file(file_path).unwrap(); std::fs::remove_file(file_path).unwrap();
model.values.remove(&column_name); model.values.remove(&column_name);
let _edit_res = E::edit_entity(db, id, model.clone()).await; let _edit_res = E::edit_entity(db.get_ref(), id, model.clone()).await;
let view_model_field = &view_model.fields.iter().find(|field| field.field_name == column_name).unwrap(); let view_model_field = &view_model.fields.iter().find(|field| field.field_name == column_name).unwrap();
ctx.insert("model_field", view_model_field); ctx.insert("model_field", view_model_field);

View File

@ -6,8 +6,8 @@ use crate::prelude::*;
use super::{ add_auth_context }; use super::{ add_auth_context };
pub fn get_admin_ctx<T: ActixAdminAppDataTrait>(session: Session, data: &web::Data<T>) -> Context { pub fn get_admin_ctx(session: Session, data: &web::Data<ActixAdmin>) -> Context {
let actix_admin = data.get_actix_admin(); let actix_admin = data.get_ref();
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.insert("entity_names", &actix_admin.entity_names); ctx.insert("entity_names", &actix_admin.entity_names);
@ -17,8 +17,8 @@ pub fn get_admin_ctx<T: ActixAdminAppDataTrait>(session: Session, data: &web::Da
ctx ctx
} }
pub async fn index<T: ActixAdminAppDataTrait>(session: Session, data: web::Data<T>) -> Result<HttpResponse, Error> { pub async fn index(session: Session, data: web::Data<ActixAdmin>) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = &data.into_inner();
let notifications: Vec<crate::ActixAdminNotification> = Vec::new(); let notifications: Vec<crate::ActixAdminNotification> = Vec::new();
let mut ctx = Context::new(); let mut ctx = Context::new();
@ -33,8 +33,8 @@ pub async fn index<T: ActixAdminAppDataTrait>(session: Session, data: web::Data<
Ok(HttpResponse::Ok().content_type("text/html").body(body)) Ok(HttpResponse::Ok().content_type("text/html").body(body))
} }
pub async fn not_found<T: ActixAdminAppDataTrait>(data: web::Data<T>) -> Result<HttpResponse, Error> { pub async fn not_found(data: web::Data<ActixAdmin>) -> Result<HttpResponse, Error> {
let body = data.get_actix_admin().tera let body = data.get_ref().tera
.render("not_found.html", &Context::new()) .render("not_found.html", &Context::new())
.map_err(|_| error::ErrorInternalServerError("Template error"))?; .map_err(|_| error::ErrorInternalServerError("Template error"))?;
Ok(HttpResponse::NotFound().content_type("text/html").body(body)) Ok(HttpResponse::NotFound().content_type("text/html").body(body))

View File

@ -1,4 +1,5 @@
use std::fmt; use std::fmt;
use sea_orm::DatabaseConnection;
use urlencoding::decode; use urlencoding::decode;
use crate::prelude::*; use crate::prelude::*;
use actix_web::{error, web, Error, HttpRequest, HttpResponse}; use actix_web::{error, web, Error, HttpRequest, HttpResponse};
@ -46,12 +47,13 @@ pub fn replace_regex(view_model: &ActixAdminViewModel, models: &mut Vec<ActixAdm
}); });
} }
pub async fn list<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( pub async fn list<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
req: HttpRequest, req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = &data.into_inner();
let entity_name = E::get_entity_name(); let entity_name = E::get_entity_name();
let view_model: &ActixAdminViewModel = actix_admin.view_models.get(&entity_name).unwrap(); let view_model: &ActixAdminViewModel = actix_admin.view_models.get(&entity_name).unwrap();
let mut errors: Vec<ActixAdminError> = Vec::new(); let mut errors: Vec<ActixAdminError> = Vec::new();
@ -74,7 +76,6 @@ pub async fn list<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
let render_partial = req.headers().contains_key("HX-Target"); let render_partial = req.headers().contains_key("HX-Target");
let search = params.search.clone().unwrap_or(String::new()); let search = params.search.clone().unwrap_or(String::new());
let db = data.get_db();
let sort_by = params let sort_by = params
.sort_by .sort_by
.clone() .clone()
@ -94,7 +95,7 @@ pub async fn list<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
af af
}).collect(); }).collect();
let result = E::list(db, page, entities_per_page, actixadminfilters, &search, &sort_by, &sort_order).await; let result = E::list(&db, page, entities_per_page, actixadminfilters, &search, &sort_by, &sort_order).await;
match result { match result {
Ok(res) => { Ok(res) => {

View File

@ -1,6 +1,7 @@
use actix_web::HttpRequest; use actix_web::HttpRequest;
use actix_web::{error, web, Error, HttpResponse}; use actix_web::{error, web, Error, HttpResponse};
use actix_session::{Session}; use actix_session::{Session};
use sea_orm::DatabaseConnection;
use tera::{Context}; use tera::{Context};
use crate::ActixAdminNotification; use crate::ActixAdminNotification;
@ -9,9 +10,10 @@ use crate::prelude::*;
use super::{Params, DEFAULT_ENTITIES_PER_PAGE}; use super::{Params, DEFAULT_ENTITIES_PER_PAGE};
use super::{ add_auth_context, user_can_access_page, render_unauthorized}; use super::{ add_auth_context, user_can_access_page, render_unauthorized};
pub async fn show<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(session: Session, req: HttpRequest, data: web::Data<T>, id: web::Path<i32>) -> Result<HttpResponse, Error> { pub async fn show<E: ActixAdminViewModelTrait>(
let actix_admin = data.get_actix_admin(); session: Session, req: HttpRequest, data: web::Data<ActixAdmin>, id: web::Path<i32>, db: web::Data<DatabaseConnection>
let db = &data.get_db(); ) -> Result<HttpResponse, Error> {
let actix_admin = &data.into_inner();
let mut ctx = Context::new(); let mut ctx = Context::new();
let entity_name = E::get_entity_name(); let entity_name = E::get_entity_name();
@ -21,7 +23,7 @@ pub async fn show<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(sessio
} }
let mut errors: Vec<crate::ActixAdminError> = Vec::new(); let mut errors: Vec<crate::ActixAdminError> = Vec::new();
let result = E::get_entity(db, id.into_inner()).await; let result = E::get_entity(&db, id.into_inner()).await;
let model; let model;
match result { match result {
Ok(res) => { Ok(res) => {

View File

@ -57,36 +57,17 @@ macro_rules! create_app (
let conn = $db.clone(); let conn = $db.clone();
let actix_admin_builder = super::create_actix_admin_builder(); let actix_admin_builder = super::create_actix_admin_builder();
let actix_admin = actix_admin_builder.get_actix_admin(); let actix_admin = actix_admin_builder.get_actix_admin();
let app_state = super::AppState {
db: conn,
actix_admin,
};
test::init_service( test::init_service(
App::new() App::new()
.app_data(actix_web::web::Data::new(app_state.clone())) .app_data(actix_web::web::Data::new(actix_admin))
.service(actix_admin_builder.get_scope::<super::AppState>()) .app_data(actix_web::web::Data::new(conn))
.service(actix_admin_builder.get_scope())
) )
.await .await
}); });
); );
#[derive(Clone)]
pub struct AppState {
pub db: DatabaseConnection,
pub actix_admin: ActixAdmin,
}
impl ActixAdminAppDataTrait for AppState {
fn get_db(&self) -> &DatabaseConnection {
&self.db
}
fn get_actix_admin(&self) -> &ActixAdmin {
&self.actix_admin
}
}
pub fn create_actix_admin_builder() -> ActixAdminBuilder { pub fn create_actix_admin_builder() -> ActixAdminBuilder {
let post_view_model = ActixAdminViewModel::from(Post); let post_view_model = ActixAdminViewModel::from(Post);
let comment_view_model = ActixAdminViewModel::from(Comment); let comment_view_model = ActixAdminViewModel::from(Comment);
@ -101,64 +82,66 @@ pub fn create_actix_admin_builder() -> ActixAdminBuilder {
}; };
let mut admin_builder = ActixAdminBuilder::new(configuration); let mut admin_builder = ActixAdminBuilder::new(configuration);
admin_builder.add_entity::<AppState, Post>(&post_view_model); admin_builder.add_entity::<Post>(&post_view_model);
admin_builder.add_entity::<AppState, Comment>(&comment_view_model); admin_builder.add_entity::<Comment>(&comment_view_model);
admin_builder.add_custom_handler_for_entity::<AppState, Comment>( admin_builder.add_custom_handler_for_entity::<Comment>(
"Create Comment From Plaintext", "Create Comment From Plaintext",
"/create_post_from_plaintext", "/create_post_from_plaintext",
web::post().to(create_post_from_plaintext::<AppState, Comment>), web::post().to(create_post_from_plaintext::<Comment>),
false, false,
); );
admin_builder.add_custom_handler_for_entity::<AppState, Post>( admin_builder.add_custom_handler_for_entity::<Post>(
"Create Post From Plaintext", "Create Post From Plaintext",
"/create_post_from_plaintext", "/create_post_from_plaintext",
web::post().to(create_post_from_plaintext::<AppState, Post>), web::post().to(create_post_from_plaintext::<Post>),
false, false,
); );
admin_builder.add_custom_handler_for_entity::<AppState, Post>( admin_builder.add_custom_handler_for_entity::<Post>(
"Edit Post From Plaintext", "Edit Post From Plaintext",
"/edit_post_from_plaintext/{id}", "/edit_post_from_plaintext/{id}",
web::post().to(edit_post_from_plaintext::<AppState, Post>), web::post().to(edit_post_from_plaintext::<Post>),
false, false,
); );
admin_builder.add_custom_handler_for_entity::<AppState, Comment>( admin_builder.add_custom_handler_for_entity::<Comment>(
"Edit Comment From Plaintext", "Edit Comment From Plaintext",
"/edit_post_from_plaintext/{id}", "/edit_post_from_plaintext/{id}",
web::post().to(edit_post_from_plaintext::<AppState, Comment>), web::post().to(edit_post_from_plaintext::<Comment>),
false, false,
); );
admin_builder admin_builder
} }
async fn create_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( async fn create_post_from_plaintext<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
req: HttpRequest, req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
text: String, text: String,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = data.get_ref();
let model = ActixAdminModel::from(text); let model = ActixAdminModel::from(text);
create_or_edit_post::<T, E>(&session, req, &data, Ok(model), None, actix_admin).await create_or_edit_post::<E>(&session, req, db, Ok(model), None, actix_admin).await
} }
async fn edit_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>( async fn edit_post_from_plaintext<E: ActixAdminViewModelTrait>(
session: Session, session: Session,
req: HttpRequest, req: HttpRequest,
data: web::Data<T>, data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
text: String, text: String,
id: web::Path<i32>, id: web::Path<i32>,
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin(); let actix_admin = data.get_ref();
let model = ActixAdminModel::from(text); let model = ActixAdminModel::from(text);
create_or_edit_post::<T, E>( create_or_edit_post::<E>(
&session, &session,
req, req,
&data, db,
Ok(model), Ok(model),
Some(id.into_inner()), Some(id.into_inner()),
actix_admin, actix_admin,

View File

@ -10,8 +10,7 @@ pub use post::Entity as Post;
pub mod prelude { pub mod prelude {
pub use crate::test_setup::helper::{ pub use crate::test_setup::helper::{
create_actix_admin_builder, create_actix_admin_builder,
setup_db, setup_db,
AppState,
BodyTest BodyTest
}; };
pub use super::comment; pub use super::comment;