keep list params while in edit or show
This commit is contained in:
parent
8ed3796e45
commit
683e473749
@ -6,11 +6,13 @@ use crate::ActixAdminNotification;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::TERA;
|
use crate::TERA;
|
||||||
|
use super::DEFAULT_ENTITIES_PER_PAGE;
|
||||||
|
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<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
session: Session,
|
session: Session,
|
||||||
_req: HttpRequest,
|
req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
_body: web::Payload,
|
_body: web::Payload,
|
||||||
_text: String,
|
_text: String,
|
||||||
@ -18,12 +20,12 @@ pub async fn create_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
|||||||
let db = &data.get_db();
|
let db = &data.get_db();
|
||||||
let model = ActixAdminModel::create_empty();
|
let model = ActixAdminModel::create_empty();
|
||||||
|
|
||||||
create_or_edit_get::<T, E>(&session, &data, db, Ok(model)).await
|
create_or_edit_get::<T, E>(&session, req, &data, db, Ok(model)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
pub async fn edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
session: Session,
|
session: Session,
|
||||||
_req: HttpRequest,
|
req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
_text: String,
|
_text: String,
|
||||||
id: web::Path<i32>
|
id: web::Path<i32>
|
||||||
@ -31,10 +33,10 @@ pub async fn edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
|||||||
let db = &data.get_db();
|
let db = &data.get_db();
|
||||||
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, &data, db, model).await
|
create_or_edit_get::<T, E>(&session, req, &data, db, model).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_or_edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(session: &Session, data: &web::Data<T>, db: &sea_orm::DatabaseConnection, model_result: Result<ActixAdminModel, ActixAdminError>) -> Result<HttpResponse, Error>{
|
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();
|
let actix_admin = &data.get_actix_admin();
|
||||||
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);
|
||||||
@ -68,11 +70,28 @@ async fn create_or_edit_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTra
|
|||||||
.map(|err| ActixAdminNotification::from(err))
|
.map(|err| ActixAdminNotification::from(err))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
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 render_partial = params.render_partial.unwrap_or(false);
|
||||||
|
let search = params.search.clone().unwrap_or(String::new());
|
||||||
|
let sort_by = params.sort_by.clone().unwrap_or(view_model.primary_key.to_string());
|
||||||
|
let sort_order = params.sort_order.as_ref().unwrap_or(&SortOrder::Asc);
|
||||||
|
|
||||||
ctx.insert("view_model", &ActixAdminViewModelSerializable::from(view_model.clone()));
|
ctx.insert("view_model", &ActixAdminViewModelSerializable::from(view_model.clone()));
|
||||||
ctx.insert("select_lists", &E::get_select_lists(db).await?);
|
ctx.insert("select_lists", &E::get_select_lists(db).await?);
|
||||||
ctx.insert("base_path", &E::get_base_path(&entity_name));
|
ctx.insert("base_path", &E::get_base_path(&entity_name));
|
||||||
ctx.insert("model", &model);
|
ctx.insert("model", &model);
|
||||||
ctx.insert("notifications", ¬ifications);
|
ctx.insert("notifications", ¬ifications);
|
||||||
|
ctx.insert("entities_per_page", &entities_per_page);
|
||||||
|
ctx.insert("render_partial", &render_partial);
|
||||||
|
ctx.insert("search", &search);
|
||||||
|
ctx.insert("sort_by", &sort_by);
|
||||||
|
ctx.insert("sort_order", &sort_order);
|
||||||
|
ctx.insert("page", &page);
|
||||||
|
|
||||||
let body = TERA
|
let body = TERA
|
||||||
.render("create_or_edit.html", &ctx)
|
.render("create_or_edit.html", &ctx)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use super::{render_unauthorized, user_can_access_page};
|
use super::{render_unauthorized, user_can_access_page};
|
||||||
|
use super::{Params, DEFAULT_ENTITIES_PER_PAGE};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::ActixAdminError;
|
use crate::ActixAdminError;
|
||||||
use crate::ActixAdminNotification;
|
use crate::ActixAdminNotification;
|
||||||
@ -7,26 +8,32 @@ use actix_multipart::Multipart;
|
|||||||
use actix_multipart::MultipartError;
|
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, HttpResponse};
|
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
|
||||||
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<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
session: Session,
|
session: Session,
|
||||||
|
req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
payload: Multipart,
|
payload: Multipart,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let actix_admin = data.get_actix_admin();
|
let actix_admin = data.get_actix_admin();
|
||||||
let model = ActixAdminModel::create_from_payload(
|
let model = ActixAdminModel::create_from_payload(
|
||||||
payload,
|
payload,
|
||||||
&format!("{}/{}", actix_admin.configuration.file_upload_directory, E::get_entity_name())
|
&format!(
|
||||||
|
"{}/{}",
|
||||||
|
actix_admin.configuration.file_upload_directory,
|
||||||
|
E::get_entity_name()
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
create_or_edit_post::<T, E>(&session, &data, model, None, actix_admin).await
|
create_or_edit_post::<T, E>(&session, req, &data, model, None, actix_admin).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
session: Session,
|
session: Session,
|
||||||
|
req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
payload: Multipart,
|
payload: Multipart,
|
||||||
id: web::Path<i32>,
|
id: web::Path<i32>,
|
||||||
@ -34,14 +41,27 @@ pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
|||||||
let actix_admin = data.get_actix_admin();
|
let actix_admin = data.get_actix_admin();
|
||||||
let model = ActixAdminModel::create_from_payload(
|
let model = ActixAdminModel::create_from_payload(
|
||||||
payload,
|
payload,
|
||||||
&format!("{}/{}", actix_admin.configuration.file_upload_directory, E::get_entity_name()),
|
&format!(
|
||||||
|
"{}/{}",
|
||||||
|
actix_admin.configuration.file_upload_directory,
|
||||||
|
E::get_entity_name()
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
create_or_edit_post::<T, E>(&session, &data, model, Some(id.into_inner()), actix_admin).await
|
create_or_edit_post::<T, E>(
|
||||||
|
&session,
|
||||||
|
req,
|
||||||
|
&data,
|
||||||
|
model,
|
||||||
|
Some(id.into_inner()),
|
||||||
|
actix_admin,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
session: &Session,
|
session: &Session,
|
||||||
|
req: HttpRequest,
|
||||||
data: &web::Data<T>,
|
data: &web::Data<T>,
|
||||||
model_res: Result<ActixAdminModel, MultipartError>,
|
model_res: Result<ActixAdminModel, MultipartError>,
|
||||||
id: Option<i32>,
|
id: Option<i32>,
|
||||||
@ -64,7 +84,16 @@ pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewMod
|
|||||||
|
|
||||||
if model.has_errors() {
|
if model.has_errors() {
|
||||||
errors.push(ActixAdminError::ValidationErrors);
|
errors.push(ActixAdminError::ValidationErrors);
|
||||||
render_form::<E>(actix_admin, view_model, db, entity_name, &model, errors).await
|
render_form::<E>(
|
||||||
|
req,
|
||||||
|
actix_admin,
|
||||||
|
view_model,
|
||||||
|
db,
|
||||||
|
entity_name,
|
||||||
|
&model,
|
||||||
|
errors,
|
||||||
|
)
|
||||||
|
.await
|
||||||
} else {
|
} else {
|
||||||
let res = match id {
|
let res = match id {
|
||||||
Some(id) => E::edit_entity(db, id, model.clone()).await,
|
Some(id) => E::edit_entity(db, id, model.clone()).await,
|
||||||
@ -72,21 +101,47 @@ pub async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewMod
|
|||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(_) => Ok(HttpResponse::SeeOther()
|
Ok(_) => {
|
||||||
|
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 _render_partial = params.render_partial.unwrap_or(false);
|
||||||
|
let search = params.search.clone().unwrap_or(String::new());
|
||||||
|
let sort_by = params
|
||||||
|
.sort_by
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(view_model.primary_key.to_string());
|
||||||
|
let sort_order = params.sort_order.as_ref().unwrap_or(&SortOrder::Asc);
|
||||||
|
|
||||||
|
Ok(HttpResponse::SeeOther()
|
||||||
.append_header((
|
.append_header((
|
||||||
header::LOCATION,
|
header::LOCATION,
|
||||||
format!("/admin/{}/list", view_model.entity_name),
|
format!("/admin/{0}/list?page={1}&search={2}&sort_by={3}&sort_order={4}&entities_per_page={5}", view_model.entity_name, page, search, sort_by, sort_order, entities_per_page),
|
||||||
))
|
))
|
||||||
.finish()),
|
.finish())
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
errors.push(e);
|
errors.push(e);
|
||||||
render_form::<E>(actix_admin, view_model, db, entity_name, &model, errors).await
|
render_form::<E>(
|
||||||
|
req,
|
||||||
|
actix_admin,
|
||||||
|
view_model,
|
||||||
|
db,
|
||||||
|
entity_name,
|
||||||
|
&model,
|
||||||
|
errors,
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn render_form<E: ActixAdminViewModelTrait>(
|
async fn render_form<E: ActixAdminViewModelTrait>(
|
||||||
|
req: HttpRequest,
|
||||||
actix_admin: &ActixAdmin,
|
actix_admin: &ActixAdmin,
|
||||||
view_model: &ActixAdminViewModel,
|
view_model: &ActixAdminViewModel,
|
||||||
db: &&sea_orm::DatabaseConnection,
|
db: &&sea_orm::DatabaseConnection,
|
||||||
@ -95,6 +150,28 @@ async fn render_form<E: ActixAdminViewModelTrait>(
|
|||||||
errors: Vec<ActixAdminError>,
|
errors: Vec<ActixAdminError>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let mut ctx = Context::new();
|
let mut ctx = Context::new();
|
||||||
|
|
||||||
|
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 render_partial = params.render_partial.unwrap_or(false);
|
||||||
|
let search = params.search.clone().unwrap_or(String::new());
|
||||||
|
let sort_by = params
|
||||||
|
.sort_by
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(view_model.primary_key.to_string());
|
||||||
|
let sort_order = params.sort_order.as_ref().unwrap_or(&SortOrder::Asc);
|
||||||
|
|
||||||
|
ctx.insert("entities_per_page", &entities_per_page);
|
||||||
|
ctx.insert("render_partial", &render_partial);
|
||||||
|
ctx.insert("search", &search);
|
||||||
|
ctx.insert("sort_by", &sort_by);
|
||||||
|
ctx.insert("sort_order", &sort_order);
|
||||||
|
ctx.insert("page", &page);
|
||||||
|
|
||||||
ctx.insert("entity_names", &actix_admin.entity_names);
|
ctx.insert("entity_names", &actix_admin.entity_names);
|
||||||
ctx.insert(
|
ctx.insert(
|
||||||
"view_model",
|
"view_model",
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
|
use actix_web::{error, web, Error, HttpRequest, HttpResponse};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde::{Deserialize};
|
use serde::{Deserialize};
|
||||||
@ -10,19 +12,7 @@ use crate::ActixAdminModel;
|
|||||||
use crate::ActixAdminNotification;
|
use crate::ActixAdminNotification;
|
||||||
use crate::TERA;
|
use crate::TERA;
|
||||||
use actix_session::{Session};
|
use actix_session::{Session};
|
||||||
use super::{ add_auth_context, user_can_access_page, render_unauthorized};
|
use super::{ add_auth_context, user_can_access_page, render_unauthorized, Params, DEFAULT_ENTITIES_PER_PAGE};
|
||||||
|
|
||||||
const DEFAULT_ENTITIES_PER_PAGE: u64 = 10;
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct Params {
|
|
||||||
page: Option<u64>,
|
|
||||||
entities_per_page: Option<u64>,
|
|
||||||
render_partial: Option<bool>,
|
|
||||||
search: Option<String>,
|
|
||||||
sort_by: Option<String>,
|
|
||||||
sort_order: Option<SortOrder>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum SortOrder {
|
pub enum SortOrder {
|
||||||
@ -30,6 +20,15 @@ pub enum SortOrder {
|
|||||||
Desc,
|
Desc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SortOrder {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
SortOrder::Asc => write!(f, "Asc"),
|
||||||
|
SortOrder::Desc => write!(f, "Desc"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn list<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
pub async fn list<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
session: Session,
|
session: Session,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
|
@ -20,4 +20,17 @@ mod helpers;
|
|||||||
pub use helpers::{ add_auth_context, user_can_access_page, render_unauthorized };
|
pub use helpers::{ add_auth_context, user_can_access_page, render_unauthorized };
|
||||||
|
|
||||||
mod file;
|
mod file;
|
||||||
pub use file::{download, delete_file};
|
pub use file::{download, delete_file};
|
||||||
|
|
||||||
|
use serde::{Deserialize};
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Params {
|
||||||
|
page: Option<u64>,
|
||||||
|
entities_per_page: Option<u64>,
|
||||||
|
render_partial: Option<bool>,
|
||||||
|
search: Option<String>,
|
||||||
|
sort_by: Option<String>,
|
||||||
|
sort_order: Option<SortOrder>
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_ENTITIES_PER_PAGE: u64 = 10;
|
@ -1,3 +1,4 @@
|
|||||||
|
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 tera::{Context};
|
use tera::{Context};
|
||||||
@ -6,9 +7,10 @@ use crate::ActixAdminNotification;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::TERA;
|
use crate::TERA;
|
||||||
|
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, data: web::Data<T>, id: web::Path<i32>) -> Result<HttpResponse, Error> {
|
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 actix_admin = data.get_actix_admin();
|
||||||
let db = &data.get_db();
|
let db = &data.get_db();
|
||||||
|
|
||||||
@ -40,11 +42,28 @@ pub async fn show<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(sessio
|
|||||||
.map(|err| ActixAdminNotification::from(err))
|
.map(|err| ActixAdminNotification::from(err))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
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 render_partial = params.render_partial.unwrap_or(false);
|
||||||
|
let search = params.search.clone().unwrap_or(String::new());
|
||||||
|
let sort_by = params.sort_by.clone().unwrap_or(view_model.primary_key.to_string());
|
||||||
|
let sort_order = params.sort_order.as_ref().unwrap_or(&SortOrder::Asc);
|
||||||
|
|
||||||
ctx.insert("model", &model);
|
ctx.insert("model", &model);
|
||||||
ctx.insert("view_model", &ActixAdminViewModelSerializable::from(view_model.clone()));
|
ctx.insert("view_model", &ActixAdminViewModelSerializable::from(view_model.clone()));
|
||||||
ctx.insert("base_path", &E::get_base_path(&entity_name));
|
ctx.insert("base_path", &E::get_base_path(&entity_name));
|
||||||
ctx.insert("entity_names", &actix_admin.entity_names);
|
ctx.insert("entity_names", &actix_admin.entity_names);
|
||||||
ctx.insert("notifications", ¬ifications);
|
ctx.insert("notifications", ¬ifications);
|
||||||
|
ctx.insert("entities_per_page", &entities_per_page);
|
||||||
|
ctx.insert("render_partial", &render_partial);
|
||||||
|
ctx.insert("search", &search);
|
||||||
|
ctx.insert("sort_by", &sort_by);
|
||||||
|
ctx.insert("sort_order", &sort_order);
|
||||||
|
ctx.insert("page", &page);
|
||||||
|
|
||||||
add_auth_context(&session, actix_admin, &mut ctx);
|
add_auth_context(&session, actix_admin, &mut ctx);
|
||||||
|
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form hx-boost="true" hx-indicator="#loading" hx-push-url="true" hx-encoding="multipart/form-data" method="post" enctype="multipart/form-data">
|
<form hx-boost="true" hx-indicator="#loading" hx-push-url="true" hx-encoding="multipart/form-data" method="post" enctype="multipart/form-data">
|
||||||
|
<input type="hidden" id="sort_by" name="sort_by" value="{{ sort_by }}">
|
||||||
|
<input type="hidden" id="sort_order" name="sort_order" value="{{ sort_order }}">
|
||||||
|
<input type="hidden" name="entities_per_page" value="{{ entities_per_page }}">
|
||||||
|
<input type="hidden" name="search" value="{{ search }}">
|
||||||
|
<input type="hidden" name="page" value="{{ page }}">
|
||||||
{% for model_field in view_model.fields -%}
|
{% for model_field in view_model.fields -%}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="{{ model_field | get_html_input_type }}" for="{{ model_field.field_name }}">
|
<label class="{{ model_field | get_html_input_type }}" for="{{ model_field.field_name }}">
|
||||||
@ -29,7 +34,17 @@
|
|||||||
<button class="button is-link" type="submit">Save</i></button>
|
<button class="button is-link" type="submit">Save</i></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<a class="button is-link is-light" href="{{ base_path }}/list">Cancel</a>
|
<a hx-vals='{
|
||||||
|
"entities_per_page" : "{{ entities_per_page }}",
|
||||||
|
"search" : "{{ search }}",
|
||||||
|
"sort_by" : "{{ sort_by }}",
|
||||||
|
"sort_order" : "{{ sort_order }}",
|
||||||
|
"render_partial" : "false",
|
||||||
|
"page" : "{{ page }}"
|
||||||
|
}' hx-boost="true" hx-push-url="true" hx-indicator="#loading"
|
||||||
|
class="button is-link is-light" href="{{ base_path }}/list">
|
||||||
|
Cancel
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -66,14 +66,14 @@
|
|||||||
<div class="is-relative">
|
<div class="is-relative">
|
||||||
{% include "loader.html" %}
|
{% include "loader.html" %}
|
||||||
<form id="table_form" hx-indicator="#loading" hx-get="/admin/{{ entity_name }}/list"
|
<form id="table_form" hx-indicator="#loading" hx-get="/admin/{{ entity_name }}/list"
|
||||||
hx-vals='{ "render_partial" : "true" }' hx-target="#{{ entity_name }}table">
|
hx-vals='{ "render_partial" : "true" }' hx-target="#{{ entity_name }}table">
|
||||||
<input type="hidden" id="sort_by" name="sort_by" value="{{ sort_by }}">
|
<input type="hidden" id="sort_by" name="sort_by" value="{{ sort_by }}">
|
||||||
<input type="hidden" id="sort_order" name="sort_order" value="{{ sort_order }}">
|
<input type="hidden" id="sort_order" name="sort_order" value="{{ sort_order }}">
|
||||||
<input type="hidden" name="entities_per_page" value="{{ entities_per_page }}">
|
<input type="hidden" name="entities_per_page" value="{{ entities_per_page }}">
|
||||||
<input type="hidden" name="search" value="{{ search }}">
|
<input type="hidden" name="search" value="{{ search }}">
|
||||||
<input type="hidden" name="page" value="{{ page }}">
|
<input type="hidden" name="page" value="{{ page }}">
|
||||||
<table class="table is-relative is-fullwidth is-hoverable is-striped">
|
<table class="table is-relative is-fullwidth is-hoverable is-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<input type="checkbox" onclick="checkAll(this)">
|
<input type="checkbox" onclick="checkAll(this)">
|
||||||
@ -88,7 +88,8 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</th>
|
</th>
|
||||||
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) | sort(attribute="list_sort_position") -%}
|
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) |
|
||||||
|
sort(attribute="list_sort_position") -%}
|
||||||
<th onclick="sort_by('{{ model_field.field_name }}');" class="is-clickable">{{
|
<th onclick="sort_by('{{ model_field.field_name }}');" class="is-clickable">{{
|
||||||
model_field.field_name | split(pat="_") | join(sep=" ") | title }}
|
model_field.field_name | split(pat="_") | join(sep=" ") | title }}
|
||||||
{% if sort_by == model_field.field_name %}
|
{% if sort_by == model_field.field_name %}
|
||||||
@ -105,70 +106,82 @@
|
|||||||
<!-- Delete Action -->
|
<!-- Delete Action -->
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</form>
|
</form>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody hx-indicator="#loading" hx-boost="true">
|
<tbody hx-indicator="#loading" hx-boost="true">
|
||||||
{% for entity in entities -%}
|
{% for entity in entities -%}
|
||||||
<tr>
|
<tr>
|
||||||
<td><input type="checkbox" name="ids" value="{{ entity.primary_key }}"></td>
|
<td><input type="checkbox" name="ids" value="{{ entity.primary_key }}"></td>
|
||||||
<td>
|
<td>
|
||||||
<a href="show/{{ entity.primary_key }}">
|
<a href="show/{{ entity.primary_key }}" hx-vals='{
|
||||||
<i class="fa-solid fa-magnifying-glass"></i> {{ entity.primary_key }}
|
"page" : "{{ page }}",
|
||||||
</a>
|
"entities_per_page" : "{{ entities_per_page }}",
|
||||||
</td>
|
"search" : "{{ search }}",
|
||||||
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) | sort(attribute="list_sort_position") -%}
|
"sort_by" : "{{ sort_by }}",
|
||||||
{% if model_field.field_type == "Checkbox" %}
|
"sort_order" : "{{ sort_order }}",
|
||||||
<td>{{ entity.values | get(key=model_field.field_name) | get_icon | safe }}</td>
|
"render_partial" : "true"
|
||||||
{% elif model_field.field_type == "FileUpload" %}
|
}' hx-target="#content">
|
||||||
<td><a href="file/{{ entity.primary_key }}/{{ model_field.field_name }}">{{
|
<i class="fa-solid fa-magnifying-glass"></i> {{ entity.primary_key }}
|
||||||
entity.values
|
</a>
|
||||||
| get(key=model_field.field_name) }}</a></td>
|
</td>
|
||||||
{% else %}
|
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) |
|
||||||
<td>{{ entity.values | get(key=model_field.field_name) }}</td>
|
sort(attribute="list_sort_position") -%}
|
||||||
{% endif %}
|
{% if model_field.field_type == "Checkbox" %}
|
||||||
{%- endfor %}
|
<td>{{ entity.values | get(key=model_field.field_name) | get_icon | safe }}</td>
|
||||||
<td>
|
{% elif model_field.field_type == "FileUpload" %}
|
||||||
<a hx-target="body" href="edit/{{ entity.primary_key }}"><i class="fa-solid fa-pen-to-square"></i></a>
|
<td><a href="file/{{ entity.primary_key }}/{{ model_field.field_name }}">{{
|
||||||
<a hx-target="closest tr" hx-confirm="Are you sure?"
|
entity.values
|
||||||
hx-delete="delete/{{ entity.primary_key }}"><i class="fa-solid fa-trash"></i></a>
|
| get(key=model_field.field_name) }}</a></td>
|
||||||
</td>
|
{% else %}
|
||||||
</tr>
|
<td>{{ entity.values | get(key=model_field.field_name) }}</td>
|
||||||
{%- endfor %}
|
{% endif %}
|
||||||
</tbody>
|
{%- endfor %}
|
||||||
<tfoot>
|
<td>
|
||||||
<tr>
|
<a hx-target="body" href="edit/{{ entity.primary_key }}" hx-vals='{
|
||||||
<td colspan="{{ view_model.fields | length + 3 }}">
|
"page" : "{{ page }}",
|
||||||
</td>
|
"entities_per_page" : "{{ entities_per_page }}",
|
||||||
</tr>
|
"search" : "{{ search }}",
|
||||||
</tfoot>
|
"sort_by" : "{{ sort_by }}",
|
||||||
|
"sort_order" : "{{ sort_order }}",
|
||||||
|
"render_partial" : "false"
|
||||||
|
}'>
|
||||||
|
<i class="fa-solid fa-pen-to-square"></i>
|
||||||
|
</a>
|
||||||
|
<a hx-target="closest tr" hx-confirm="Are you sure?" hx-delete="delete/{{ entity.primary_key }}">
|
||||||
|
<i class="fa-solid fa-trash"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{%- endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="{{ view_model.fields | length + 3 }}">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<nav hx-boost="true"
|
<nav hx-boost="true" hx-push-url="true" hx-target="#{{ entity_name }}table" hx-vals='{
|
||||||
hx-push-url="true"
|
|
||||||
hx-target="#{{ entity_name }}table"
|
|
||||||
hx-vals='{
|
|
||||||
"entities_per_page" : "{{ entities_per_page }}",
|
"entities_per_page" : "{{ entities_per_page }}",
|
||||||
"search" : "{{ search }}",
|
"search" : "{{ search }}",
|
||||||
"sort_by" : "{{ sort_by }}",
|
"sort_by" : "{{ sort_by }}",
|
||||||
"sort_order" : "{{ sort_order }}",
|
"sort_order" : "{{ sort_order }}",
|
||||||
"render_partial" : "true"
|
"render_partial" : "true"
|
||||||
}' hx-indicator="#loading" class="pagination is-rounded is-centered" role="pagination"
|
}' hx-indicator="#loading" class="pagination is-rounded is-centered" role="pagination" aria-label="pagination">
|
||||||
aria-label="pagination">
|
|
||||||
{% if page > 1 %}
|
{% if page > 1 %}
|
||||||
<a href="?&page={{ page - 1 }}"
|
<a href="?&page={{ page - 1 }}" class="pagination-previous left-arrow-click"><i
|
||||||
class="pagination-previous left-arrow-click"><i class="fa-solid fa-arrow-left"></i>
|
class="fa-solid fa-arrow-left"></i>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if page < num_pages %} <a
|
{% if page < num_pages %} <a href="?page={{ page + 1 }}" class="pagination-next right-arrow-click"><i
|
||||||
href="?page={{ page + 1 }}"
|
class="fa-solid fa-arrow-right"></i>
|
||||||
class="pagination-next right-arrow-click"><i class="fa-solid fa-arrow-right"></i>
|
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<ul class="pagination-list">
|
<ul class="pagination-list">
|
||||||
<li>
|
<li>
|
||||||
<a class="pagination-link {% if page == 1 %}is-current{% endif %}"
|
<a class="pagination-link {% if page == 1 %}is-current{% endif %}" href="?page={{ 1 }}"
|
||||||
href="?page={{ 1 }}"
|
|
||||||
aria-label="Goto page 1">1</a>
|
aria-label="Goto page 1">1</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@ -176,8 +189,7 @@
|
|||||||
</li>
|
</li>
|
||||||
{% for i in range(start=min_show_page,end=max_show_page) %}
|
{% for i in range(start=min_show_page,end=max_show_page) %}
|
||||||
<li><a class="pagination-link {% if page == i+1 %}is-current{% endif %}"
|
<li><a class="pagination-link {% if page == i+1 %}is-current{% endif %}"
|
||||||
aria-label="Goto page {{ i + 1 }}"
|
aria-label="Goto page {{ i + 1 }}" href="?page={{ i + 1 }}">{{
|
||||||
href="?page={{ i + 1 }}">{{
|
|
||||||
i + 1 }}</a></li>
|
i + 1 }}</a></li>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
<li>
|
<li>
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
{% if model_field.field_type == "Checkbox" %}
|
{% if model_field.field_type == "Checkbox" %}
|
||||||
<td>{{ model.values | get(key=model_field.field_name) | get_icon | safe }}</td>
|
<td>{{ model.values | get(key=model_field.field_name) | get_icon | safe }}</td>
|
||||||
{% elif model_field.field_type == "FileUpload" %}
|
{% elif model_field.field_type == "FileUpload" %}
|
||||||
<td><a href="file/{{ view_model.primary_key }}/{{ model_field.field_name }}">{{ model.values | get(key=model_field.field_name) }}</a></td>
|
<td><a href="file/{{ view_model.primary_key }}/{{ model_field.field_name }}">{{ model.values |
|
||||||
|
get(key=model_field.field_name) }}</a></td>
|
||||||
{% else %}
|
{% else %}
|
||||||
<td>{{ model.values | get(key=model_field.field_name) }}</td>
|
<td>{{ model.values | get(key=model_field.field_name) }}</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -21,11 +22,18 @@
|
|||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<a class="button is-link is-light" href="{{ base_path }}/list">Back</a>
|
<a hx-vals='{
|
||||||
|
"entities_per_page" : "{{ entities_per_page }}",
|
||||||
|
"search" : "{{ search }}",
|
||||||
|
"sort_by" : "{{ sort_by }}",
|
||||||
|
"sort_order" : "{{ sort_order }}",
|
||||||
|
"render_partial" : "false",
|
||||||
|
"page" : "{{ page }}"
|
||||||
|
}' hx-boost="true" hx-push-url="true" hx-indicator="#loading"
|
||||||
|
class="button is-link is-light" href="{{ base_path }}/list">Back</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
@ -1,5 +1,6 @@
|
|||||||
use actix_admin::prelude::*;
|
use actix_admin::prelude::*;
|
||||||
use actix_session::Session;
|
use actix_session::Session;
|
||||||
|
use actix_web::HttpRequest;
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use actix_web::Error;
|
use actix_web::Error;
|
||||||
use actix_web::HttpResponse;
|
use actix_web::HttpResponse;
|
||||||
@ -135,16 +136,18 @@ pub fn create_actix_admin_builder() -> ActixAdminBuilder {
|
|||||||
|
|
||||||
async fn create_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
async fn create_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
session: Session,
|
session: Session,
|
||||||
|
req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
text: String,
|
text: String,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let actix_admin = data.get_actix_admin();
|
let actix_admin = data.get_actix_admin();
|
||||||
let model = ActixAdminModel::from(text);
|
let model = ActixAdminModel::from(text);
|
||||||
create_or_edit_post::<T, E>(&session, &data, Ok(model), None, actix_admin).await
|
create_or_edit_post::<T, E>(&session, req, &data, Ok(model), None, actix_admin).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn edit_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
async fn edit_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
session: Session,
|
session: Session,
|
||||||
|
req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
text: String,
|
text: String,
|
||||||
id: web::Path<i32>,
|
id: web::Path<i32>,
|
||||||
@ -153,6 +156,7 @@ async fn edit_post_from_plaintext<T: ActixAdminAppDataTrait, E: ActixAdminViewMo
|
|||||||
let model = ActixAdminModel::from(text);
|
let model = ActixAdminModel::from(text);
|
||||||
create_or_edit_post::<T, E>(
|
create_or_edit_post::<T, E>(
|
||||||
&session,
|
&session,
|
||||||
|
req,
|
||||||
&data,
|
&data,
|
||||||
Ok(model),
|
Ok(model),
|
||||||
Some(id.into_inner()),
|
Some(id.into_inner()),
|
||||||
|
Loading…
Reference in New Issue
Block a user