move function out of lib
This commit is contained in:
parent
657ad8ffc9
commit
7648c4bced
@ -1,16 +1,16 @@
|
|||||||
use actix_web::{error, guard, web, Error, HttpRequest, HttpResponse};
|
|
||||||
use actix_web::{ dev, App, FromRequest};
|
|
||||||
use actix_web::error::ErrorBadRequest;
|
use actix_web::error::ErrorBadRequest;
|
||||||
use serde::{Deserialize, Serialize};
|
use actix_web::{dev, App, FromRequest};
|
||||||
use std::collections::HashMap;
|
use actix_web::{error, guard, web, Error, HttpRequest, HttpResponse};
|
||||||
use tera::{Context, Tera};
|
use futures::future::{err, ok, Ready};
|
||||||
use futures::future::{ok, err, Ready};
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
use sea_orm::EntityTrait;
|
use sea_orm::EntityTrait;
|
||||||
use sea_orm::ModelTrait;
|
use sea_orm::ModelTrait;
|
||||||
use std::pin::Pin;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use tera::{Context, Tera};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
@ -20,7 +20,8 @@ const DEFAULT_POSTS_PER_PAGE: usize = 5;
|
|||||||
|
|
||||||
// templates
|
// templates
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref TERA: Tera = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
|
static ref TERA: Tera =
|
||||||
|
Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paging
|
// Paging
|
||||||
@ -33,19 +34,18 @@ pub struct Params {
|
|||||||
// Fields
|
// Fields
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub enum Field {
|
pub enum Field {
|
||||||
Text
|
Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppDataTrait
|
// AppDataTrait
|
||||||
pub trait AppDataTrait {
|
pub trait AppDataTrait {
|
||||||
fn get_db(&self) -> &DatabaseConnection;
|
fn get_db(&self) -> &DatabaseConnection;
|
||||||
fn get_view_model_map(&self) -> &HashMap<&'static str, ActixAdminViewModel>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActixAdminModel
|
// ActixAdminModel
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait ActixAdminModelTrait : Clone {
|
pub trait ActixAdminModelTrait: Clone {
|
||||||
async fn list(&self, db: &DatabaseConnection, page: usize, posts_per_page: usize) -> Vec<&str>;
|
async fn list(db: &DatabaseConnection, page: usize, posts_per_page: usize) -> Vec<&str>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
@ -54,68 +54,47 @@ pub struct ActixAdminModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ActixAdminViewModel
|
// ActixAdminViewModel
|
||||||
pub trait ActixAdminViewModelTrait : Clone {
|
pub trait ActixAdminViewModelTrait: Clone {
|
||||||
fn get_model_name(&self) -> &str;
|
fn get_model_name(&self) -> &str;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub struct ActixAdminViewModel {
|
pub struct ActixAdminViewModel {
|
||||||
pub entity_name: &'static str,
|
pub entity_name: String
|
||||||
pub admin_model: ActixAdminModel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ActixAdminController
|
// ActixAdminController
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ActixAdmin {
|
pub struct ActixAdmin {
|
||||||
view_models: HashMap<&'static str, ActixAdminViewModel>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActixAdmin {
|
impl ActixAdmin {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let actix_admin = ActixAdmin {
|
let actix_admin = ActixAdmin {
|
||||||
view_models: HashMap::new(),
|
|
||||||
};
|
};
|
||||||
actix_admin
|
actix_admin
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_scope<T: AppDataTrait + 'static>(self, _app_state: &T) -> actix_web::Scope {
|
pub fn create_scope<T: AppDataTrait + 'static>(self, _app_state: &T) -> actix_web::Scope {
|
||||||
let mut scope = web::scope("/admin").route("/", web::get().to(index::<T>));
|
let scope = web::scope("/admin").route("/", web::get().to(index::<T>));
|
||||||
|
|
||||||
for view_model in self.view_models {
|
|
||||||
scope = scope.service(
|
|
||||||
web::scope(&format!("/{}", view_model.0)).route("/list", web::get().to(list::<T>))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
scope
|
scope
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_entity(mut self, view_model: ActixAdminViewModel) -> Self {
|
|
||||||
self.view_models.insert(view_model.entity_name, view_model);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_view_model_map(&self) -> HashMap<&'static str, ActixAdminViewModel> {
|
|
||||||
self.view_models.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn index<T: AppDataTrait>(data: web::Data<T>) -> Result<HttpResponse, Error> {
|
async fn index<T: AppDataTrait>(data: web::Data<T>) -> Result<HttpResponse, Error> {
|
||||||
let view_models = Vec::from_iter(data.get_view_model_map().values());
|
|
||||||
|
|
||||||
|
let view_models: Vec<&str> = Vec::new();
|
||||||
let mut ctx = Context::new();
|
let mut ctx = Context::new();
|
||||||
ctx.insert("view_models", &view_models);
|
ctx.insert("view_models", &view_models);
|
||||||
|
|
||||||
let body = TERA
|
let body = TERA
|
||||||
.render("index.html", &ctx)
|
.render("index.html", &ctx)
|
||||||
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
|
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
|
||||||
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list<T: AppDataTrait>(req: HttpRequest, data: web::Data<T>) -> Result<HttpResponse, Error> {
|
pub fn list_model(req: HttpRequest, view_model: ActixAdminViewModel) -> Result<HttpResponse, Error> {
|
||||||
let view_model = data.get_view_model_map().get("posts").unwrap();
|
|
||||||
|
|
||||||
let db = &data.get_db();
|
|
||||||
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
|
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
|
||||||
|
|
||||||
let page = params.page.unwrap_or(1);
|
let page = params.page.unwrap_or(1);
|
||||||
@ -133,7 +112,7 @@ async fn list<T: AppDataTrait>(req: HttpRequest, data: web::Data<T>) -> Result<H
|
|||||||
ctx.insert("columns", &columns);
|
ctx.insert("columns", &columns);
|
||||||
|
|
||||||
let body = TERA
|
let body = TERA
|
||||||
.render("list.html", &ctx)
|
.render("list.html", &ctx)
|
||||||
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
|
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
|
||||||
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
||||||
}
|
}
|
47
src/entity/comment.rs
Normal file
47
src/entity/comment.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use actix_admin::{ DeriveActixAdminModel };
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize, DeriveActixAdminModel)]
|
||||||
|
#[sea_orm(table_name = "comment")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
pub id: i32,
|
||||||
|
pub title: String,
|
||||||
|
#[sea_orm(column_type = "Text")]
|
||||||
|
pub text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
|
||||||
|
impl From<Entity> for ActixAdminModel {
|
||||||
|
fn from(entity: Entity) -> Self {
|
||||||
|
ActixAdminModel {
|
||||||
|
fields: Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ActixAdminModelTrait for Entity {
|
||||||
|
async fn list(&self, db: &DatabaseConnection, page: usize, posts_per_page: usize) -> Vec<&str> {
|
||||||
|
use sea_orm::{ query::* };
|
||||||
|
let paginator = Entity::find()
|
||||||
|
.order_by_asc(Column::Id)
|
||||||
|
.paginate(db, posts_per_page);
|
||||||
|
let entities = paginator
|
||||||
|
.fetch_page(page - 1)
|
||||||
|
.await
|
||||||
|
.expect("could not retrieve entities");
|
||||||
|
//entities to ActixAdminModel
|
||||||
|
vec![
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use actix_admin::{ DeriveActixAdminModel };
|
use actix_admin::{ DeriveActixAdminModel, ActixAdminViewModel };
|
||||||
|
|
||||||
#[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")]
|
||||||
@ -19,18 +19,17 @@ pub enum Relation {}
|
|||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
impl From<Entity> for ActixAdminViewModel {
|
||||||
impl From<Entity> for ActixAdminModel {
|
|
||||||
fn from(entity: Entity) -> Self {
|
fn from(entity: Entity) -> Self {
|
||||||
ActixAdminModel {
|
ActixAdminViewModel {
|
||||||
fields: Vec::new()
|
entity_name: entity.table_name().to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl ActixAdminModelTrait for Entity {
|
impl ActixAdminModelTrait for Entity {
|
||||||
async fn list(&self, db: &DatabaseConnection, page: usize, posts_per_page: usize) -> Vec<&str> {
|
async fn list(db: &DatabaseConnection, page: usize, posts_per_page: usize) -> Vec<&str> {
|
||||||
use sea_orm::{ query::* };
|
use sea_orm::{ query::* };
|
||||||
let paginator = Entity::find()
|
let paginator = Entity::find()
|
||||||
.order_by_asc(Column::Id)
|
.order_by_asc(Column::Id)
|
||||||
|
35
src/main.rs
35
src/main.rs
@ -1,16 +1,15 @@
|
|||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
use actix_session::{Session, CookieSession};
|
use actix_session::{Session, CookieSession};
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
use actix_web::{web, App, HttpResponse, HttpServer, HttpRequest, Error};
|
||||||
use tera::{ Tera, Context};
|
use tera::{ Tera, Context};
|
||||||
use oauth2::basic::BasicClient;
|
use oauth2::basic::BasicClient;
|
||||||
use oauth2::{ RedirectUrl };
|
use oauth2::{ RedirectUrl };
|
||||||
use std::time::{Duration};
|
use std::time::{Duration};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::collections::HashMap;
|
|
||||||
use sea_orm::{{ DatabaseConnection, ConnectOptions }};
|
use sea_orm::{{ DatabaseConnection, ConnectOptions }};
|
||||||
|
|
||||||
use actix_admin::{ AppDataTrait as ActixAdminAppDataTrait, ActixAdminViewModel, ActixAdminModel};
|
use actix_admin::{ AppDataTrait as ActixAdminAppDataTrait, ActixAdminViewModel, ActixAdminModelTrait};
|
||||||
use azure_auth::{ AzureAuth, UserInfo, AppDataTrait as AzureAuthAppDataTrait };
|
use azure_auth::{ AzureAuth, UserInfo, AppDataTrait as AzureAuthAppDataTrait };
|
||||||
|
|
||||||
mod entity;
|
mod entity;
|
||||||
@ -21,17 +20,12 @@ pub struct AppState {
|
|||||||
pub oauth: BasicClient,
|
pub oauth: BasicClient,
|
||||||
pub tmpl: Tera,
|
pub tmpl: Tera,
|
||||||
pub db: DatabaseConnection,
|
pub db: DatabaseConnection,
|
||||||
pub view_model_map: HashMap<&'static str, ActixAdminViewModel>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActixAdminAppDataTrait for AppState {
|
impl ActixAdminAppDataTrait for AppState {
|
||||||
fn get_db(&self) -> &DatabaseConnection {
|
fn get_db(&self) -> &DatabaseConnection {
|
||||||
&self.db
|
&self.db
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_view_model_map(&self) -> &HashMap<&'static str, ActixAdminViewModel> {
|
|
||||||
&self.view_model_map
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AzureAuthAppDataTrait for AppState {
|
impl AzureAuthAppDataTrait for AppState {
|
||||||
@ -82,19 +76,10 @@ async fn main() {
|
|||||||
let conn = sea_orm::Database::connect(opt).await.unwrap();
|
let conn = sea_orm::Database::connect(opt).await.unwrap();
|
||||||
let _ = entity::create_post_table(&conn).await;
|
let _ = entity::create_post_table(&conn).await;
|
||||||
|
|
||||||
let viewmodel_entity = ActixAdminViewModel {
|
|
||||||
entity_name: "posts",
|
|
||||||
admin_model: ActixAdminModel::from(Post)
|
|
||||||
};
|
|
||||||
|
|
||||||
let actix_admin = actix_admin::ActixAdmin::new()
|
|
||||||
.add_entity(viewmodel_entity.clone());
|
|
||||||
|
|
||||||
let app_state = AppState {
|
let app_state = AppState {
|
||||||
oauth: client,
|
oauth: client,
|
||||||
tmpl: tera,
|
tmpl: tera,
|
||||||
db: conn,
|
db: conn,
|
||||||
view_model_map: actix_admin.get_view_model_map()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
@ -102,8 +87,14 @@ async fn main() {
|
|||||||
.app_data(web::Data::new(app_state.clone()))
|
.app_data(web::Data::new(app_state.clone()))
|
||||||
.wrap(CookieSession::signed(&[0; 32]).secure(false))
|
.wrap(CookieSession::signed(&[0; 32]).secure(false))
|
||||||
.route("/", web::get().to(index))
|
.route("/", web::get().to(index))
|
||||||
.service(actix_admin.clone().create_scope(&app_state))
|
|
||||||
.service(azure_auth.clone().create_scope(&app_state))
|
.service(azure_auth.clone().create_scope(&app_state))
|
||||||
|
.service(
|
||||||
|
actix_admin::ActixAdmin::new()
|
||||||
|
.create_scope(&app_state)
|
||||||
|
.service(
|
||||||
|
web::scope(&format!("/{}", "posts")).route("/list", web::get().to(list)),
|
||||||
|
)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:5000")
|
.bind("127.0.0.1:5000")
|
||||||
.expect("Can not bind to port 5000")
|
.expect("Can not bind to port 5000")
|
||||||
@ -111,3 +102,11 @@ async fn main() {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Actix admin Routes to be auto generated
|
||||||
|
async fn list(req: HttpRequest, data: web::Data<AppState>)-> Result<HttpResponse, Error> {
|
||||||
|
let db = &data.get_db();
|
||||||
|
let entities = Post::list(db, 1, 5);
|
||||||
|
let model = ActixAdminViewModel::from(Post);
|
||||||
|
actix_admin::list_model(req, model)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user