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
}
// Custom Validation Functions
impl ActixAdminModelValidationTrait<ActiveModel> for Entity {}
// Custom Search Filters
impl ActixAdminModelFilterTrait<Entity> for Entity {}
```
## Derive Implementations
@ -65,7 +68,7 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
let mut admin_builder = ActixAdminBuilder::new(configuration);
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
}
@ -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```:
```rust
admin_builder.add_entity::<AppState, Comment>(&comment_view_model);
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, "Group 1");
admin_builder.add_entity::<Comment>(&comment_view_model);
admin_builder.add_entity_to_category::<Comment>(&comment_view_model, "Group 1");
```
## 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.
```rust
async fn custom_index<T: ActixAdminAppDataTrait + AppDataTrait>(
async fn custom_index(
session: Session,
data: web::Data<T>
data: web::Data<AppState>
actix_admin: web::Data<ActixAdmin>
) -> Result<HttpResponse, Error> {
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()
.render("custom_index.html", &ctx).unwrap();
let body = data.tmpl.render("custom_index.html", &ctx).unwrap();
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:
```rust
let mut admin_builder = ActixAdminBuilder::new(configuration);
admin_builder.add_custom_handler_for_index::<AppState>(
web::get().to(custom_index::<AppState>)
admin_builder.add_custom_handler_for_index(
web::get().to(custom_index)
);
```
@ -53,7 +53,7 @@ Similarly to the custom index above, the builder accepts additional routes to be
```rust
// This will be shown in the top level menu
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
@ -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
let show_in_menu = true;
let some_category = "Some Category";
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity::<AppState, Comment>(
admin_builder.add_entity_to_category::<Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity::<Comment>(
"My custom handler",
"/custom_handler",
web::get().to(custom_handler::<AppState, Comment>),
web::get().to(custom_handler::<Comment>),
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"
let show_in_menu = true;
let some_category = "Some Category";
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity_in_category::<AppState, Comment>(
admin_builder.add_entity_to_category::<Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity_in_category::<Comment>(
"My custom handler",
"/custom_handler",
web::get().to(custom_handler::<AppState, Comment>),
web::get().to(custom_handler::<Comment>),
some_category,
show_in_menu
);

View File

@ -12,30 +12,7 @@ weight: 1
Cargo.toml:
```cargo
[dependencies]
actix-admin = "0.3.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
}
}
actix-admin = "0.4.0"
```
## 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.
```rust
let conn = sea_orm::Database::connect(opt).await.unwrap();
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()
.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(
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 oauth2::basic::BasicClient;
use oauth2::RedirectUrl;
use sea_orm::{ConnectOptions, DatabaseConnection};
use sea_orm::{ConnectOptions};
use std::env;
use std::time::Duration;
use tera::{Context, Tera};
@ -18,28 +18,7 @@ use entity::{Post, Comment};
#[derive(Clone)]
pub struct AppState {
pub oauth: BasicClient,
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
}
pub tmpl: Tera
}
impl AzureAuthAppDataTrait for AppState {
@ -48,42 +27,36 @@ impl AzureAuthAppDataTrait for AppState {
}
}
async fn custom_handler<
T: ActixAdminAppDataTrait + AppDataTrait,
E: ActixAdminViewModelTrait,
>(
async fn custom_handler(
session: Session,
data: web::Data<T>,
data: web::Data<AppState>,
actix_admin: web::Data<ActixAdmin>,
_text: String
) -> Result<HttpResponse, Error> {
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()
.render("custom_handler.html", &ctx).unwrap();
let body = data.tmpl.render("custom_handler.html", &ctx).unwrap();
Ok(HttpResponse::Ok().content_type("text/html").body(body))
}
async fn custom_index<
T: ActixAdminAppDataTrait + AppDataTrait
>(
async fn custom_index(
session: Session,
data: web::Data<T>,
data: web::Data<AppState>,
actix_admin: web::Data<ActixAdmin>,
_text: String
) -> Result<HttpResponse, Error> {
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()
.render("custom_index.html", &ctx).unwrap();
let body = data.tmpl.render("custom_index.html", &ctx).unwrap();
Ok(HttpResponse::Ok().content_type("text/html").body(body))
}
async fn index(session: Session, data: web::Data<AppState>) -> HttpResponse {
let login = session.get::<UserInfo>("user_info").unwrap();
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);
admin_builder.add_custom_handler_for_index::<AppState>(
web::get().to(custom_index::<AppState>)
admin_builder.add_custom_handler_for_index(
web::get().to(custom_index)
);
admin_builder.add_entity::<AppState, 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 not in Menu", "/custom_route_not_in_menu", web::get().to(custom_index::<AppState>), false);
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), true);
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";
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity_in_category::<AppState, Comment>(
admin_builder.add_entity_to_category::<Comment>(&comment_view_model, some_category);
admin_builder.add_custom_handler_for_entity_in_category::<Comment>(
"My custom handler",
"/custom_handler",
web::get().to(custom_handler::<AppState, Comment>),
web::get().to(custom_handler),
some_category,
true
);
@ -179,18 +152,18 @@ async fn main() {
let app_state = AppState {
oauth: client.clone(),
tmpl: tera.clone(),
db: conn.clone(),
actix_admin: actix_admin,
tmpl: tera.clone()
};
App::new()
.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()))
.route("/", web::get().to(index))
.service(azure_auth.clone().create_scope::<AppState>())
.service(
actix_admin_builder.get_scope::<AppState>()
actix_admin_builder.get_scope()
)
.wrap(middleware::Logger::default())
})

View File

@ -2,26 +2,11 @@ extern crate serde_derive;
use actix_admin::prelude::*;
use actix_web::{web, App, HttpServer, middleware};
use sea_orm::{ConnectOptions, DatabaseConnection};
use sea_orm::{ConnectOptions};
use std::time::Duration;
mod entity;
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 {
let configuration = ActixAdminConfiguration {
enable_auth: false,
@ -35,13 +20,13 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
let mut admin_builder = ActixAdminBuilder::new(configuration);
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 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);
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
}
@ -60,7 +45,7 @@ fn get_db_options() -> ConnectOptions {
#[actix_rt::main]
async fn main() {
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;
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 app_state = AppState {
db: conn.clone(),
actix_admin: actix_admin_builder.get_actix_admin(),
};
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(
actix_admin_builder.get_scope::<AppState>()
actix_admin_builder.get_scope()
)
.wrap(middleware::Logger::default())
})

View File

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

View File

@ -31,7 +31,7 @@ pub mod prelude {
ActixAdminViewModelSerializable, ActixAdminViewModelTrait, ActixAdminViewModelFilter
};
pub use crate::{hashmap, ActixAdminSelectListTrait};
pub use crate::{ActixAdmin, ActixAdminAppDataTrait, ActixAdminConfiguration, ActixAdminError};
pub use crate::{ActixAdmin, ActixAdminConfiguration, ActixAdminError};
pub use actix_admin_macros::{
DeriveActixAdmin, DeriveActixAdminEnumSelectList, DeriveActixAdminModel,
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
#[async_trait]
pub trait ActixAdminSelectListTrait {

View File

@ -1,4 +1,5 @@
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
use sea_orm::DatabaseConnection;
use tera::{Context};
use actix_session::{Session};
use crate::ActixAdminError;
@ -9,34 +10,36 @@ use super::DEFAULT_ENTITIES_PER_PAGE;
use super::Params;
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,
req: HttpRequest,
data: web::Data<T>,
data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
_body: web::Payload,
_text: String,
) -> Result<HttpResponse, Error> {
let db = &data.get_db();
let db = db.get_ref();
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,
req: HttpRequest,
data: web::Data<T>,
data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
_text: String,
id: web::Path<i32>
) -> Result<HttpResponse, Error> {
let db = &data.get_db();
let db = db.get_ref();
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>{
let actix_admin = &data.get_actix_admin();
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_ref();
let mut ctx = Context::new();
add_auth_context(&session, actix_admin, &mut ctx);
let entity_names = &actix_admin.entity_names;

View File

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

View File

@ -3,16 +3,18 @@ use crate::prelude::*;
use actix_session::Session;
use actix_web::http::header;
use actix_web::{web, Error, HttpRequest, HttpResponse};
use sea_orm::DatabaseConnection;
use tera::Context;
pub async fn delete<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
pub async fn delete<E: ActixAdminViewModelTrait>(
session: Session,
_req: HttpRequest,
data: web::Data<T>,
data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
_text: String,
id: web::Path<i32>,
) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin();
let actix_admin = &data.into_inner();
let entity_name = E::get_entity_name();
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);
}
let db = &data.get_db();
let db = &db.get_ref();
let id = id.into_inner();
let model_result = E::get_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,
_req: HttpRequest,
data: web::Data<T>,
data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
form: web::Form<Vec<(String, String)>>,
) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin();
let actix_admin = data.get_ref();
let entity_name = E::get_entity_name();
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);
}
let db = &data.get_db();
let db = &db.get_ref();
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();

View File

@ -1,13 +1,14 @@
use actix_web::{web, error, Error, HttpResponse, HttpRequest};
use actix_session::{Session};
use sea_orm::DatabaseConnection;
use tera::{Context};
use crate::prelude::*;
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> {
let actix_admin = data.get_actix_admin();
let db = &data.get_db();
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.into_inner();
let db = &db.into_inner();
let ctx = Context::new();
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> {
let actix_admin = data.get_actix_admin();
let db = &data.get_db();
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.into_inner();
let mut ctx = Context::new();
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 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;
match result {
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());
std::fs::remove_file(file_path).unwrap();
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();
ctx.insert("model_field", view_model_field);

View File

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

View File

@ -1,4 +1,5 @@
use std::fmt;
use sea_orm::DatabaseConnection;
use urlencoding::decode;
use crate::prelude::*;
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,
req: HttpRequest,
data: web::Data<T>,
data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>
) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin();
let actix_admin = &data.into_inner();
let entity_name = E::get_entity_name();
let view_model: &ActixAdminViewModel = actix_admin.view_models.get(&entity_name).unwrap();
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 search = params.search.clone().unwrap_or(String::new());
let db = data.get_db();
let sort_by = params
.sort_by
.clone()
@ -94,7 +95,7 @@ pub async fn list<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
af
}).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 {
Ok(res) => {

View File

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

View File

@ -57,36 +57,17 @@ macro_rules! create_app (
let conn = $db.clone();
let actix_admin_builder = super::create_actix_admin_builder();
let actix_admin = actix_admin_builder.get_actix_admin();
let app_state = super::AppState {
db: conn,
actix_admin,
};
test::init_service(
App::new()
.app_data(actix_web::web::Data::new(app_state.clone()))
.service(actix_admin_builder.get_scope::<super::AppState>())
.app_data(actix_web::web::Data::new(actix_admin))
.app_data(actix_web::web::Data::new(conn))
.service(actix_admin_builder.get_scope())
)
.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 {
let post_view_model = ActixAdminViewModel::from(Post);
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);
admin_builder.add_entity::<AppState, Post>(&post_view_model);
admin_builder.add_entity::<AppState, Comment>(&comment_view_model);
admin_builder.add_entity::<Post>(&post_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_post_from_plaintext",
web::post().to(create_post_from_plaintext::<AppState, Comment>),
web::post().to(create_post_from_plaintext::<Comment>),
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",
web::post().to(create_post_from_plaintext::<AppState, Post>),
web::post().to(create_post_from_plaintext::<Post>),
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/{id}",
web::post().to(edit_post_from_plaintext::<AppState, Post>),
web::post().to(edit_post_from_plaintext::<Post>),
false,
);
admin_builder.add_custom_handler_for_entity::<AppState, Comment>(
admin_builder.add_custom_handler_for_entity::<Comment>(
"Edit Comment From Plaintext",
"/edit_post_from_plaintext/{id}",
web::post().to(edit_post_from_plaintext::<AppState, Comment>),
web::post().to(edit_post_from_plaintext::<Comment>),
false,
);
admin_builder
}
async fn create_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
async fn create_post_from_plaintext<E: ActixAdminViewModelTrait>(
session: Session,
req: HttpRequest,
data: web::Data<T>,
data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
text: String,
) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin();
let actix_admin = data.get_ref();
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,
req: HttpRequest,
data: web::Data<T>,
data: web::Data<ActixAdmin>,
db: web::Data<DatabaseConnection>,
text: String,
id: web::Path<i32>,
) -> Result<HttpResponse, Error> {
let actix_admin = data.get_actix_admin();
let actix_admin = data.get_ref();
let model = ActixAdminModel::from(text);
create_or_edit_post::<T, E>(
create_or_edit_post::<E>(
&session,
req,
&data,
db,
Ok(model),
Some(id.into_inner()),
actix_admin,

View File

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