split into multiple files
This commit is contained in:
parent
90a17e64d3
commit
6dc1401550
69
actix_admin/src/builder.rs
Normal file
69
actix_admin/src/builder.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use actix_web::{web};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::ActixAdmin;
|
||||||
|
use crate::ActixAdminViewModelTrait;
|
||||||
|
use crate::ActixAdminViewModel;
|
||||||
|
use crate::AppDataTrait;
|
||||||
|
|
||||||
|
use crate::routes::list;
|
||||||
|
use crate::routes::create_get;
|
||||||
|
use crate::routes::create_post;
|
||||||
|
use crate::routes::index;
|
||||||
|
|
||||||
|
pub struct ActixAdminBuilder {
|
||||||
|
pub scopes: Vec<actix_web::Scope>,
|
||||||
|
pub actix_admin: ActixAdmin,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ActixAdminBuilderTrait {
|
||||||
|
fn new() -> Self;
|
||||||
|
fn add_entity<T: AppDataTrait + 'static, E: ActixAdminViewModelTrait + 'static>(&mut self, view_model: &ActixAdminViewModel);
|
||||||
|
fn get_scope<T: AppDataTrait + 'static>(self) -> actix_web::Scope;
|
||||||
|
fn get_actix_admin(&self) -> ActixAdmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActixAdminBuilderTrait for ActixAdminBuilder {
|
||||||
|
fn new() -> Self {
|
||||||
|
ActixAdminBuilder {
|
||||||
|
actix_admin: ActixAdmin {
|
||||||
|
entity_names: Vec::new(),
|
||||||
|
view_models: HashMap::new(),
|
||||||
|
},
|
||||||
|
scopes: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_entity<T: AppDataTrait + 'static, E: ActixAdminViewModelTrait + 'static>(
|
||||||
|
&mut self,
|
||||||
|
view_model: &ActixAdminViewModel,
|
||||||
|
) {
|
||||||
|
self.scopes.push(
|
||||||
|
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>)),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.actix_admin.entity_names.push(E::get_entity_name());
|
||||||
|
//let view_model_cloned = view_model.clone();
|
||||||
|
let key = E::get_entity_name();
|
||||||
|
self.actix_admin.view_models.insert(key, view_model.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_scope<T: AppDataTrait + 'static>(self) -> actix_web::Scope {
|
||||||
|
let mut scope = web::scope("/admin").route("/", web::get().to(index::<T>));
|
||||||
|
for entity_scope in self.scopes {
|
||||||
|
scope = scope.service(entity_scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
scope
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_actix_admin(&self) -> ActixAdmin {
|
||||||
|
self.actix_admin.clone()
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,24 @@
|
|||||||
use actix_web::http::header;
|
|
||||||
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tera::{Context, Tera};
|
use tera::{Tera};
|
||||||
|
|
||||||
pub use actix_admin_macros::DeriveActixAdminModel;
|
pub use actix_admin_macros::DeriveActixAdminModel;
|
||||||
|
|
||||||
const DEFAULT_ENTITIES_PER_PAGE: usize = 5;
|
mod view_model;
|
||||||
|
pub use view_model::ActixAdminViewModel;
|
||||||
|
pub use view_model::ActixAdminViewModelTrait;
|
||||||
|
|
||||||
|
mod model;
|
||||||
|
pub use model::ActixAdminModel;
|
||||||
|
pub use model::ActixAdminModelTrait;
|
||||||
|
|
||||||
|
mod builder;
|
||||||
|
pub use builder::ActixAdminBuilder;
|
||||||
|
pub use builder::ActixAdminBuilderTrait;
|
||||||
|
|
||||||
|
mod routes;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! hashmap {
|
macro_rules! hashmap {
|
||||||
@ -26,13 +35,6 @@ lazy_static! {
|
|||||||
Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
|
Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paging
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct Params {
|
|
||||||
page: Option<usize>,
|
|
||||||
entities_per_page: Option<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields
|
// Fields
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub enum ActixAdminField {
|
pub enum ActixAdminField {
|
||||||
@ -46,211 +48,9 @@ pub trait AppDataTrait {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ActixAdminModel
|
// ActixAdminModel
|
||||||
#[async_trait]
|
|
||||||
pub trait ActixAdminModelTrait {
|
|
||||||
async fn list_model(
|
|
||||||
db: &DatabaseConnection,
|
|
||||||
page: usize,
|
|
||||||
posts_per_page: usize,
|
|
||||||
) -> Vec<ActixAdminModel>;
|
|
||||||
fn get_fields() -> Vec<(String, ActixAdminField)>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
|
||||||
pub struct ActixAdminModel {
|
|
||||||
pub values: HashMap<String, String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ActixAdminViewModel
|
|
||||||
#[async_trait(?Send)]
|
|
||||||
pub trait ActixAdminViewModelTrait {
|
|
||||||
async fn list(
|
|
||||||
db: &DatabaseConnection,
|
|
||||||
page: usize,
|
|
||||||
entities_per_page: usize,
|
|
||||||
) -> Vec<ActixAdminModel>;
|
|
||||||
async fn create_entity(db: &DatabaseConnection, model: ActixAdminModel) -> ActixAdminModel;
|
|
||||||
fn get_entity_name() -> String;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
|
||||||
pub struct ActixAdminViewModel {
|
|
||||||
pub entity_name: String,
|
|
||||||
pub fields: Vec<(String, ActixAdminField)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ActixAdmin {
|
pub struct ActixAdmin {
|
||||||
pub entity_names: Vec<String>,
|
pub entity_names: Vec<String>,
|
||||||
pub view_models: HashMap<String, ActixAdminViewModel>,
|
pub view_models: HashMap<String, ActixAdminViewModel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ActixAdminBuilder {
|
|
||||||
pub scopes: Vec<actix_web::Scope>,
|
|
||||||
pub actix_admin: ActixAdmin,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ActixAdminBuilderTrait {
|
|
||||||
fn new() -> Self;
|
|
||||||
fn add_entity<T: AppDataTrait + 'static, E: ActixAdminViewModelTrait + 'static>(&mut self, view_model: &ActixAdminViewModel);
|
|
||||||
fn get_scope<T: AppDataTrait + 'static>(self) -> actix_web::Scope;
|
|
||||||
fn get_actix_admin(&self) -> ActixAdmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActixAdminBuilderTrait for ActixAdminBuilder {
|
|
||||||
fn new() -> Self {
|
|
||||||
ActixAdminBuilder {
|
|
||||||
actix_admin: ActixAdmin {
|
|
||||||
entity_names: Vec::new(),
|
|
||||||
view_models: HashMap::new(),
|
|
||||||
},
|
|
||||||
scopes: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_entity<T: AppDataTrait + 'static, E: ActixAdminViewModelTrait + 'static>(
|
|
||||||
&mut self,
|
|
||||||
view_model: &ActixAdminViewModel,
|
|
||||||
) {
|
|
||||||
self.scopes.push(
|
|
||||||
web::scope(&format!("/{}", E::get_entity_name()))
|
|
||||||
.route("/list", web::get().to(self::list::<T, E>))
|
|
||||||
.route("/create", web::get().to(self::create_get::<T, E>))
|
|
||||||
.route("/create", web::post().to(self::create_post::<T, E>)),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.actix_admin.entity_names.push(E::get_entity_name());
|
|
||||||
//let view_model_cloned = view_model.clone();
|
|
||||||
let key = E::get_entity_name();
|
|
||||||
self.actix_admin.view_models.insert(key, view_model.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_scope<T: AppDataTrait + 'static>(self) -> actix_web::Scope {
|
|
||||||
let mut scope = web::scope("/admin").route("/", web::get().to(index::<T>));
|
|
||||||
for entity_scope in self.scopes {
|
|
||||||
scope = scope.service(entity_scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
scope
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_actix_admin(&self) -> ActixAdmin {
|
|
||||||
self.actix_admin.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for ActixAdminModel {
|
|
||||||
fn from(string: String) -> Self {
|
|
||||||
let mut hashmap = HashMap::new();
|
|
||||||
let key_values: Vec<&str> = string.split('&').collect();
|
|
||||||
for key_value in key_values {
|
|
||||||
let mut iter = key_value.splitn(2, '=');
|
|
||||||
hashmap.insert(
|
|
||||||
iter.next().unwrap().to_string(),
|
|
||||||
iter.next().unwrap().to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ActixAdminModel { values: hashmap }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActixAdminModel {
|
|
||||||
pub fn get_value<T: std::str::FromStr>(&self, key: &str) -> Option<T> {
|
|
||||||
println!("get value for key {}", key);
|
|
||||||
let value = self.values.get(key).unwrap().to_string().parse::<T>();
|
|
||||||
match value {
|
|
||||||
Ok(val) => Some(val),
|
|
||||||
Err(_) => None, //panic!("key {} could not be parsed", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn index<T: AppDataTrait>(data: web::Data<T>) -> Result<HttpResponse, Error> {
|
|
||||||
let entity_names = &data.get_actix_admin().entity_names;
|
|
||||||
let mut ctx = Context::new();
|
|
||||||
ctx.insert("entity_names", &entity_names);
|
|
||||||
|
|
||||||
let body = TERA
|
|
||||||
.render("index.html", &ctx)
|
|
||||||
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
|
|
||||||
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn list<T: AppDataTrait, E: ActixAdminViewModelTrait>(
|
|
||||||
req: HttpRequest,
|
|
||||||
data: web::Data<T>,
|
|
||||||
) -> Result<HttpResponse, Error> {
|
|
||||||
let entity_name = E::get_entity_name();
|
|
||||||
let actix_admin = data.get_actix_admin();
|
|
||||||
let view_model: &ActixAdminViewModel = actix_admin.view_models.get(&entity_name).unwrap();
|
|
||||||
let entity_names = &data.get_actix_admin().entity_names;
|
|
||||||
|
|
||||||
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
|
|
||||||
|
|
||||||
let page = params.page.unwrap_or(1);
|
|
||||||
let entities_per_page = params
|
|
||||||
.entities_per_page
|
|
||||||
.unwrap_or(DEFAULT_ENTITIES_PER_PAGE);
|
|
||||||
|
|
||||||
let db = data.get_db();
|
|
||||||
let entities: Vec<ActixAdminModel> = E::list(db, page, entities_per_page).await;
|
|
||||||
|
|
||||||
let mut ctx = Context::new();
|
|
||||||
ctx.insert("entity_names", &entity_names);
|
|
||||||
ctx.insert("entities", &entities);
|
|
||||||
ctx.insert("page", &page);
|
|
||||||
ctx.insert("entities_per_page", &entities_per_page);
|
|
||||||
ctx.insert("num_pages", "5" /*&num_pages*/);
|
|
||||||
ctx.insert("view_model", &view_model);
|
|
||||||
|
|
||||||
let body = TERA
|
|
||||||
.render("list.html", &ctx)
|
|
||||||
.map_err(|err| error::ErrorInternalServerError(err))?;
|
|
||||||
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create_get<T: AppDataTrait, E: ActixAdminViewModelTrait>(
|
|
||||||
_req: HttpRequest,
|
|
||||||
data: web::Data<T>,
|
|
||||||
_body: web::Payload,
|
|
||||||
_text: String,
|
|
||||||
) -> Result<HttpResponse, Error> {
|
|
||||||
let _db = &data.get_db();
|
|
||||||
let entity_name = E::get_entity_name();
|
|
||||||
let entity_names = &data.get_actix_admin().entity_names;
|
|
||||||
|
|
||||||
let actix_admin = data.get_actix_admin();
|
|
||||||
|
|
||||||
let view_model = actix_admin.view_models.get(&entity_name).unwrap();
|
|
||||||
|
|
||||||
let mut ctx = Context::new();
|
|
||||||
ctx.insert("entity_names", &entity_names);
|
|
||||||
ctx.insert("view_model", &view_model);
|
|
||||||
ctx.insert("model_fields", &view_model.fields);
|
|
||||||
|
|
||||||
let body = TERA
|
|
||||||
.render("create.html", &ctx)
|
|
||||||
.map_err(|err| error::ErrorInternalServerError(err))?;
|
|
||||||
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create_post<T: AppDataTrait, E: ActixAdminViewModelTrait>(
|
|
||||||
_req: HttpRequest,
|
|
||||||
data: web::Data<T>,
|
|
||||||
text: String,
|
|
||||||
) -> Result<HttpResponse, Error> {
|
|
||||||
let db = &data.get_db();
|
|
||||||
let entity_name = E::get_entity_name();
|
|
||||||
let actix_admin = data.get_actix_admin();
|
|
||||||
let view_model = actix_admin.view_models.get(&entity_name).unwrap();
|
|
||||||
let mut admin_model = ActixAdminModel::from(text);
|
|
||||||
admin_model = E::create_entity(db, admin_model).await;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Found()
|
|
||||||
.append_header((
|
|
||||||
header::LOCATION,
|
|
||||||
format!("/admin/{}/list", view_model.entity_name),
|
|
||||||
))
|
|
||||||
.finish())
|
|
||||||
}
|
|
||||||
|
48
actix_admin/src/model.rs
Normal file
48
actix_admin/src/model.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use sea_orm::DatabaseConnection;
|
||||||
|
use serde::{Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::ActixAdminField;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait ActixAdminModelTrait {
|
||||||
|
async fn list_model(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
page: usize,
|
||||||
|
posts_per_page: usize,
|
||||||
|
) -> Vec<ActixAdminModel>;
|
||||||
|
fn get_fields() -> Vec<(String, ActixAdminField)>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
pub struct ActixAdminModel {
|
||||||
|
pub values: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for ActixAdminModel {
|
||||||
|
fn from(string: String) -> Self {
|
||||||
|
let mut hashmap = HashMap::new();
|
||||||
|
let key_values: Vec<&str> = string.split('&').collect();
|
||||||
|
for key_value in key_values {
|
||||||
|
let mut iter = key_value.splitn(2, '=');
|
||||||
|
hashmap.insert(
|
||||||
|
iter.next().unwrap().to_string(),
|
||||||
|
iter.next().unwrap().to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActixAdminModel { values: hashmap }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActixAdminModel {
|
||||||
|
pub fn get_value<T: std::str::FromStr>(&self, key: &str) -> Option<T> {
|
||||||
|
println!("get value for key {}", key);
|
||||||
|
let value = self.values.get(key).unwrap().to_string().parse::<T>();
|
||||||
|
match value {
|
||||||
|
Ok(val) => Some(val),
|
||||||
|
Err(_) => None, //panic!("key {} could not be parsed", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
actix_admin/src/routes/create_get.rs
Normal file
31
actix_admin/src/routes/create_get.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
|
||||||
|
use tera::{Context};
|
||||||
|
|
||||||
|
use crate::AppDataTrait;
|
||||||
|
use crate::ActixAdminViewModelTrait;
|
||||||
|
use crate::TERA;
|
||||||
|
|
||||||
|
pub async fn create_get<T: AppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
|
_req: HttpRequest,
|
||||||
|
data: web::Data<T>,
|
||||||
|
_body: web::Payload,
|
||||||
|
_text: String,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let _db = &data.get_db();
|
||||||
|
let entity_name = E::get_entity_name();
|
||||||
|
let entity_names = &data.get_actix_admin().entity_names;
|
||||||
|
|
||||||
|
let actix_admin = data.get_actix_admin();
|
||||||
|
|
||||||
|
let view_model = actix_admin.view_models.get(&entity_name).unwrap();
|
||||||
|
|
||||||
|
let mut ctx = Context::new();
|
||||||
|
ctx.insert("entity_names", &entity_names);
|
||||||
|
ctx.insert("view_model", &view_model);
|
||||||
|
ctx.insert("model_fields", &view_model.fields);
|
||||||
|
|
||||||
|
let body = TERA
|
||||||
|
.render("create.html", &ctx)
|
||||||
|
.map_err(|err| error::ErrorInternalServerError(err))?;
|
||||||
|
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
||||||
|
}
|
26
actix_admin/src/routes/create_post.rs
Normal file
26
actix_admin/src/routes/create_post.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use actix_web::http::header;
|
||||||
|
use actix_web::{web, Error, HttpRequest, HttpResponse};
|
||||||
|
|
||||||
|
use crate::AppDataTrait;
|
||||||
|
use crate::ActixAdminViewModelTrait;
|
||||||
|
use crate::ActixAdminModel;
|
||||||
|
|
||||||
|
pub async fn create_post<T: AppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
|
_req: HttpRequest,
|
||||||
|
data: web::Data<T>,
|
||||||
|
text: String,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let db = &data.get_db();
|
||||||
|
let entity_name = E::get_entity_name();
|
||||||
|
let actix_admin = data.get_actix_admin();
|
||||||
|
let view_model = actix_admin.view_models.get(&entity_name).unwrap();
|
||||||
|
let mut admin_model = ActixAdminModel::from(text);
|
||||||
|
admin_model = E::create_entity(db, admin_model).await;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Found()
|
||||||
|
.append_header((
|
||||||
|
header::LOCATION,
|
||||||
|
format!("/admin/{}/list", view_model.entity_name),
|
||||||
|
))
|
||||||
|
.finish())
|
||||||
|
}
|
16
actix_admin/src/routes/index.rs
Normal file
16
actix_admin/src/routes/index.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use actix_web::{error, web, Error, HttpResponse};
|
||||||
|
use tera::{Context};
|
||||||
|
|
||||||
|
use crate::AppDataTrait;
|
||||||
|
use crate::TERA;
|
||||||
|
|
||||||
|
pub async fn index<T: AppDataTrait>(data: web::Data<T>) -> Result<HttpResponse, Error> {
|
||||||
|
let entity_names = &data.get_actix_admin().entity_names;
|
||||||
|
let mut ctx = Context::new();
|
||||||
|
ctx.insert("entity_names", &entity_names);
|
||||||
|
|
||||||
|
let body = TERA
|
||||||
|
.render("index.html", &ctx)
|
||||||
|
.map_err(|_| error::ErrorInternalServerError("Template error"))?;
|
||||||
|
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
||||||
|
}
|
50
actix_admin/src/routes/list.rs
Normal file
50
actix_admin/src/routes/list.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
|
||||||
|
use serde::{Deserialize};
|
||||||
|
use tera::{Context};
|
||||||
|
|
||||||
|
use crate::AppDataTrait;
|
||||||
|
use crate::ActixAdminViewModelTrait;
|
||||||
|
use crate::ActixAdminViewModel;
|
||||||
|
use crate::ActixAdminModel;
|
||||||
|
use crate::TERA;
|
||||||
|
|
||||||
|
const DEFAULT_ENTITIES_PER_PAGE: usize = 5;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Params {
|
||||||
|
page: Option<usize>,
|
||||||
|
entities_per_page: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list<T: AppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
|
req: HttpRequest,
|
||||||
|
data: web::Data<T>,
|
||||||
|
) -> Result<HttpResponse, Error> {
|
||||||
|
let entity_name = E::get_entity_name();
|
||||||
|
let actix_admin = data.get_actix_admin();
|
||||||
|
let view_model: &ActixAdminViewModel = actix_admin.view_models.get(&entity_name).unwrap();
|
||||||
|
let entity_names = &data.get_actix_admin().entity_names;
|
||||||
|
|
||||||
|
let params = web::Query::<Params>::from_query(req.query_string()).unwrap();
|
||||||
|
|
||||||
|
let page = params.page.unwrap_or(1);
|
||||||
|
let entities_per_page = params
|
||||||
|
.entities_per_page
|
||||||
|
.unwrap_or(DEFAULT_ENTITIES_PER_PAGE);
|
||||||
|
|
||||||
|
let db = data.get_db();
|
||||||
|
let entities: Vec<ActixAdminModel> = E::list(db, page, entities_per_page).await;
|
||||||
|
|
||||||
|
let mut ctx = Context::new();
|
||||||
|
ctx.insert("entity_names", &entity_names);
|
||||||
|
ctx.insert("entities", &entities);
|
||||||
|
ctx.insert("page", &page);
|
||||||
|
ctx.insert("entities_per_page", &entities_per_page);
|
||||||
|
ctx.insert("num_pages", "5" /*&num_pages*/);
|
||||||
|
ctx.insert("view_model", &view_model);
|
||||||
|
|
||||||
|
let body = TERA
|
||||||
|
.render("list.html", &ctx)
|
||||||
|
.map_err(|err| error::ErrorInternalServerError(err))?;
|
||||||
|
Ok(HttpResponse::Ok().content_type("text/html").body(body))
|
||||||
|
}
|
11
actix_admin/src/routes/mod.rs
Normal file
11
actix_admin/src/routes/mod.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
mod create_get;
|
||||||
|
pub use create_get::create_get;
|
||||||
|
|
||||||
|
mod create_post;
|
||||||
|
pub use create_post::create_post;
|
||||||
|
|
||||||
|
mod index;
|
||||||
|
pub use index::index;
|
||||||
|
|
||||||
|
mod list;
|
||||||
|
pub use list::list;
|
23
actix_admin/src/view_model.rs
Normal file
23
actix_admin/src/view_model.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use sea_orm::DatabaseConnection;
|
||||||
|
use serde::{Serialize};
|
||||||
|
|
||||||
|
use crate::ActixAdminModel;
|
||||||
|
use crate::ActixAdminField;
|
||||||
|
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
pub trait ActixAdminViewModelTrait {
|
||||||
|
async fn list(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
page: usize,
|
||||||
|
entities_per_page: usize,
|
||||||
|
) -> Vec<ActixAdminModel>;
|
||||||
|
async fn create_entity(db: &DatabaseConnection, model: ActixAdminModel) -> ActixAdminModel;
|
||||||
|
fn get_entity_name() -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
pub struct ActixAdminViewModel {
|
||||||
|
pub entity_name: String,
|
||||||
|
pub fields: Vec<(String, ActixAdminField)>,
|
||||||
|
}
|
@ -10,7 +10,6 @@ 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, DatabaseConnection};
|
||||||
//use sea_orm::{entity::*, query::*};
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tera::{Context, Tera};
|
use tera::{Context, Tera};
|
||||||
|
Loading…
Reference in New Issue
Block a user