update sea-orm and fix empty list when no searchable conditions
This commit is contained in:
parent
473147e80a
commit
223ad29266
20
Cargo.toml
20
Cargo.toml
@ -23,23 +23,23 @@ actix-web = "^4.3.1"
|
|||||||
actix-session = { version = "^0.7.2", features = [] }
|
actix-session = { version = "^0.7.2", features = [] }
|
||||||
actix-multipart = "^0.6.0"
|
actix-multipart = "^0.6.0"
|
||||||
actix-files = "^0.6.2"
|
actix-files = "^0.6.2"
|
||||||
futures-util = "0.3.27"
|
futures-util = "0.3.28"
|
||||||
chrono = "0.4.24"
|
chrono = "0.4.26"
|
||||||
tera = "^1.18.1"
|
tera = "^1.19.0"
|
||||||
async-trait = "^0.1.67"
|
async-trait = "^0.1.68"
|
||||||
lazy_static = "^1.4.0"
|
lazy_static = "^1.4.0"
|
||||||
itertools = "^0.10.5"
|
itertools = "^0.10.5"
|
||||||
serde = "^1.0.158"
|
serde = "^1.0.164"
|
||||||
serde_derive = "^1.0.158"
|
serde_derive = "^1.0.164"
|
||||||
sea-orm = { version = "^0.10.6", features = [], default-features = false }
|
sea-orm = { version = "^0.11.3", features = [], default-features = false }
|
||||||
actix-admin-macros = { version = "0.4.0", path = "actix_admin_macros" }
|
actix-admin-macros = { version = "0.4.0", path = "actix_admin_macros" }
|
||||||
derive_more = "0.99.17"
|
derive_more = "0.99.17"
|
||||||
regex = "1.7.1"
|
regex = "1.8.4"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
sea-orm = { version = "^0.10.6", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = true }
|
sea-orm = { version = "^0.11.3", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = true }
|
||||||
actix-rt = "2.8.0"
|
actix-rt = "2.8.0"
|
||||||
azure_auth = { path = "./examples/azure_auth/azure_auth" }
|
azure_auth = { path = "./examples/azure_auth/azure_auth" }
|
||||||
oauth2 = "4.3"
|
oauth2 = "4.4.1"
|
||||||
dotenv = "0.15"
|
dotenv = "0.15"
|
||||||
actix-session = { version = "0.7.2", features = ["cookie-session"] }
|
actix-session = { version = "0.7.2", features = ["cookie-session"] }
|
@ -15,12 +15,16 @@ mod attributes;
|
|||||||
mod model_fields;
|
mod model_fields;
|
||||||
|
|
||||||
#[proc_macro_derive(DeriveActixAdminEnumSelectList, attributes(actix_admin))]
|
#[proc_macro_derive(DeriveActixAdminEnumSelectList, attributes(actix_admin))]
|
||||||
pub fn derive_actix_admin_enum_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_actix_admin_enum_select_list(
|
||||||
|
input: proc_macro::TokenStream,
|
||||||
|
) -> proc_macro::TokenStream {
|
||||||
get_select_list_from_enum(input)
|
get_select_list_from_enum(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(DeriveActixAdminModelSelectList, attributes(actix_admin))]
|
#[proc_macro_derive(DeriveActixAdminModelSelectList, attributes(actix_admin))]
|
||||||
pub fn derive_actix_admin_model_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_actix_admin_model_select_list(
|
||||||
|
input: proc_macro::TokenStream,
|
||||||
|
) -> proc_macro::TokenStream {
|
||||||
get_select_list_from_model(input)
|
get_select_list_from_model(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,22 +147,40 @@ pub fn derive_actix_admin_view_model(input: proc_macro::TokenStream) -> proc_mac
|
|||||||
pub fn derive_actix_admin_model(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_actix_admin_model(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let fields = get_fields_for_tokenstream(input);
|
let fields = get_fields_for_tokenstream(input);
|
||||||
|
|
||||||
let field_names = get_fields_as_tokenstream(&fields, |model_field| -> String { model_field.ident.to_string() });
|
let field_names = get_fields_as_tokenstream(&fields, |model_field| -> String {
|
||||||
let field_html_input_type = get_fields_as_tokenstream(&fields, |model_field| -> String { model_field.html_input_type.to_string() });
|
model_field.ident.to_string()
|
||||||
let field_list_regex_mask = get_fields_as_tokenstream(&fields, |model_field| -> String { model_field.list_regex_mask.to_string() });
|
});
|
||||||
let field_select_list = get_fields_as_tokenstream(&fields, |model_field| -> String { model_field.select_list.to_string() });
|
let field_html_input_type = get_fields_as_tokenstream(&fields, |model_field| -> String {
|
||||||
let is_option_list = get_fields_as_tokenstream(&fields, |model_field| -> bool { model_field.is_option() });
|
model_field.html_input_type.to_string()
|
||||||
|
});
|
||||||
|
let field_list_regex_mask = get_fields_as_tokenstream(&fields, |model_field| -> String {
|
||||||
|
model_field.list_regex_mask.to_string()
|
||||||
|
});
|
||||||
|
let field_select_list = get_fields_as_tokenstream(&fields, |model_field| -> String {
|
||||||
|
model_field.select_list.to_string()
|
||||||
|
});
|
||||||
|
let is_option_list =
|
||||||
|
get_fields_as_tokenstream(&fields, |model_field| -> bool { model_field.is_option() });
|
||||||
let fields_for_create_model = get_fields_for_create_model(&fields);
|
let fields_for_create_model = get_fields_for_create_model(&fields);
|
||||||
let fields_for_from_model = get_fields_for_from_model(&fields);
|
let fields_for_from_model = get_fields_for_from_model(&fields);
|
||||||
let field_for_primary_key = get_field_for_primary_key(&fields);
|
let field_for_primary_key = get_field_for_primary_key(&fields);
|
||||||
let fields_for_validate_model = get_fields_for_validate_model(&fields);
|
let fields_for_validate_model = get_fields_for_validate_model(&fields);
|
||||||
let fields_type_path = get_fields_as_tokenstream(&fields, |model_field| -> String { model_field.get_type_path_string() });
|
let fields_type_path = get_fields_as_tokenstream(&fields, |model_field| -> String {
|
||||||
let fields_textarea = get_fields_as_tokenstream(&fields, |model_field| -> bool { model_field.textarea });
|
model_field.get_type_path_string()
|
||||||
let fields_file_upload = get_fields_as_tokenstream(&fields, |model_field| -> bool { model_field.file_upload });
|
});
|
||||||
|
let fields_textarea =
|
||||||
|
get_fields_as_tokenstream(&fields, |model_field| -> bool { model_field.textarea });
|
||||||
|
let fields_file_upload =
|
||||||
|
get_fields_as_tokenstream(&fields, |model_field| -> bool { model_field.file_upload });
|
||||||
let fields_match_name_to_columns = get_match_name_to_column(&fields);
|
let fields_match_name_to_columns = get_match_name_to_column(&fields);
|
||||||
let fields_list_sort_positions = get_fields_as_tokenstream(&fields, |model_field| -> usize { model_field.list_sort_position });
|
let fields_list_sort_positions = get_fields_as_tokenstream(&fields, |model_field| -> usize {
|
||||||
let fields_list_hide_column = get_fields_as_tokenstream(&fields, |model_field| -> bool { model_field.list_hide_column });
|
model_field.list_sort_position
|
||||||
|
});
|
||||||
|
let fields_list_hide_column = get_fields_as_tokenstream(&fields, |model_field| -> bool {
|
||||||
|
model_field.list_hide_column
|
||||||
|
});
|
||||||
let fields_searchable = get_actix_admin_fields_searchable(&fields);
|
let fields_searchable = get_actix_admin_fields_searchable(&fields);
|
||||||
|
let has_searchable_fields = fields_searchable.len() > 0;
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
actix_admin::prelude::lazy_static! {
|
actix_admin::prelude::lazy_static! {
|
||||||
@ -260,26 +282,28 @@ pub fn derive_actix_admin_model(input: proc_macro::TokenStream) -> proc_macro::T
|
|||||||
#[actix_admin::prelude::async_trait]
|
#[actix_admin::prelude::async_trait]
|
||||||
impl ActixAdminModelTrait for Entity {
|
impl ActixAdminModelTrait for Entity {
|
||||||
async fn list_model(db: &DatabaseConnection, page: u64, posts_per_page: u64, search: &str, sort_by: &str, sort_order: &SortOrder) -> Result<(u64, Vec<ActixAdminModel>), ActixAdminError> {
|
async fn list_model(db: &DatabaseConnection, page: u64, posts_per_page: u64, search: &str, sort_by: &str, sort_order: &SortOrder) -> Result<(u64, Vec<ActixAdminModel>), ActixAdminError> {
|
||||||
use sea_orm::{ query::* };
|
|
||||||
|
|
||||||
let sort_column = match sort_by {
|
let sort_column = match sort_by {
|
||||||
#(#fields_match_name_to_columns)*
|
#(#fields_match_name_to_columns)*
|
||||||
_ => panic!("Unknown column")
|
_ => panic!("Unknown column")
|
||||||
};
|
};
|
||||||
|
|
||||||
let query = if sort_order.eq(&SortOrder::Asc) {
|
let mut query = if sort_order.eq(&SortOrder::Asc) {
|
||||||
Entity::find().order_by_asc(sort_column)
|
Entity::find().order_by_asc(sort_column)
|
||||||
} else {
|
} else {
|
||||||
Entity::find().order_by_desc(sort_column)
|
Entity::find().order_by_desc(sort_column)
|
||||||
};
|
};
|
||||||
|
|
||||||
let paginator = query
|
if (#has_searchable_fields) {
|
||||||
|
query = query
|
||||||
.filter(
|
.filter(
|
||||||
Condition::any()
|
Condition::any()
|
||||||
#(#fields_searchable)*
|
#(#fields_searchable)*
|
||||||
)
|
)
|
||||||
.paginate(db, posts_per_page);
|
}
|
||||||
|
|
||||||
|
let paginator = query.paginate(db, posts_per_page);
|
||||||
let num_pages = paginator.num_pages().await?;
|
let num_pages = paginator.num_pages().await?;
|
||||||
|
|
||||||
let mut model_entities = Vec::new();
|
let mut model_entities = Vec::new();
|
||||||
if (num_pages == 0) { return Ok((num_pages, model_entities)) };
|
if (num_pages == 0) { return Ok((num_pages, model_entities)) };
|
||||||
let entities = paginator
|
let entities = paginator
|
||||||
|
@ -32,10 +32,10 @@ name = "actix-admin-example"
|
|||||||
path = "main.rs"
|
path = "main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "^4.2.1"
|
actix-web = "^4.3.1"
|
||||||
actix-rt = "2.7.0"
|
actix-rt = "2.7.0"
|
||||||
actix-multipart = "^0.4.0"
|
actix-multipart = "^0.4.0"
|
||||||
sea-orm = { version = "^0.11.1", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = true }
|
sea-orm = { version = "^0.11.3", features = [ "sqlx-sqlite", "runtime-actix-native-tls", "macros" ], default-features = true }
|
||||||
chrono = "0.4.23"
|
chrono = "0.4.23"
|
||||||
tera = "^1.17.1"
|
tera = "^1.17.1"
|
||||||
serde = "^1.0.152"
|
serde = "^1.0.152"
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
// setup
|
// setup
|
||||||
use sea_orm::sea_query::{ForeignKeyCreateStatement, ColumnDef, TableCreateStatement};
|
use sea_orm::sea_query::{ForeignKeyCreateStatement, ColumnDef, TableCreateStatement};
|
||||||
use sea_orm::{Set, EntityTrait, error::*, sea_query, ConnectionTrait, DbConn, ExecResult};
|
use sea_orm::{Set, EntityTrait, error::*, sea_query, ConnectionTrait, DbConn, ExecResult };
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
|
pub mod user;
|
||||||
pub use comment::Entity as Comment;
|
pub use comment::Entity as Comment;
|
||||||
pub use post::Entity as Post;
|
pub use post::Entity as Post;
|
||||||
|
pub use user::Entity as User;
|
||||||
use chrono::{Local, Duration, DurationRound};
|
use chrono::{Local, Duration, DurationRound};
|
||||||
use sea_orm::prelude::Decimal;
|
use sea_orm::prelude::Decimal;
|
||||||
|
|
||||||
@ -61,7 +63,22 @@ pub async fn create_post_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
)
|
)
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let res = create_table(db, &stmt).await;
|
let _res = create_table(db, &stmt).await;
|
||||||
|
|
||||||
|
let stmt = sea_query::Table::create()
|
||||||
|
.table(user::Entity)
|
||||||
|
.if_not_exists()
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(post::Column::Id)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.auto_increment()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(user::Column::Name).string().not_null())
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
|
let _res = create_table(db, &stmt).await;
|
||||||
|
|
||||||
for i in 1..1000 {
|
for i in 1..1000 {
|
||||||
let row = post::ActiveModel {
|
let row = post::ActiveModel {
|
||||||
@ -87,5 +104,13 @@ pub async fn create_post_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
|||||||
let _res = Comment::insert(row).exec(db).await;
|
let _res = Comment::insert(row).exec(db).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
for i in 1..100 {
|
||||||
|
let row = user::ActiveModel {
|
||||||
|
name: Set(format!("user {}", i)),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let _res = User::insert(row).exec(db).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
_res
|
||||||
}
|
}
|
||||||
|
20
examples/basic/entity/user.rs
Normal file
20
examples/basic/entity/user.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use actix_admin::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize, DeriveActixAdmin, DeriveActixAdminModel, DeriveActixAdminViewModel)]
|
||||||
|
#[sea_orm(table_name = "user")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
#[actix_admin(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ActixAdminModelValidationTrait<ActiveModel> for Entity {}
|
@ -5,7 +5,7 @@ use actix_web::{web, App, HttpServer, middleware};
|
|||||||
use sea_orm::{ConnectOptions, DatabaseConnection};
|
use sea_orm::{ConnectOptions, DatabaseConnection};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
mod entity;
|
mod entity;
|
||||||
use entity::{Post, Comment};
|
use entity::{Post, Comment, User};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
@ -33,13 +33,14 @@ fn create_actix_admin_builder() -> ActixAdminBuilder {
|
|||||||
|
|
||||||
let mut admin_builder = ActixAdminBuilder::new(configuration);
|
let mut admin_builder = ActixAdminBuilder::new(configuration);
|
||||||
|
|
||||||
|
|
||||||
let post_view_model = ActixAdminViewModel::from(Post);
|
let post_view_model = ActixAdminViewModel::from(Post);
|
||||||
admin_builder.add_entity::<AppState, Post>(&post_view_model);
|
admin_builder.add_entity::<AppState, Post>(&post_view_model);
|
||||||
|
|
||||||
let some_category = "Groupings";
|
let some_category = "Group";
|
||||||
let comment_view_model = ActixAdminViewModel::from(Comment);
|
let comment_view_model = ActixAdminViewModel::from(Comment);
|
||||||
admin_builder.add_entity_to_category::<AppState, Comment>(&comment_view_model, some_category);
|
admin_builder.add_entity_to_category::<AppState, 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
|
admin_builder
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sort_by(column, order) {
|
function sort_by(column) {
|
||||||
document.getElementsByName("sort_order").forEach((e) => e.value = order);
|
console.log(column);
|
||||||
|
current_sort_order = document.getElementsByName("sort_order")[0].value;
|
||||||
|
if (current_sort_order == "Asc") {
|
||||||
|
document.getElementsByName("sort_order").forEach((e) => e.value = "Desc");
|
||||||
|
} else {
|
||||||
|
document.getElementsByName("sort_order").forEach((e) => e.value = "Asc");
|
||||||
|
}
|
||||||
document.getElementsByName("sort_by").forEach((e) => e.value = column);
|
document.getElementsByName("sort_by").forEach((e) => e.value = column);
|
||||||
document.getElementById('table_form').requestSubmit();
|
document.getElementById('table_form').requestSubmit();
|
||||||
}
|
}
|
||||||
|
@ -71,63 +71,33 @@
|
|||||||
<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-narrow is-fullwidth is-hoverable is-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<input type="checkbox" onclick="checkAll(this)">
|
<input type="checkbox" onclick="checkAll(this)">
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th onclick="sort_by('{{ view_model.primary_key }}');" class="is-clickable">{{
|
||||||
<div class="dropdown is-hoverable">
|
view_model.primary_key | title }}
|
||||||
<div class="dropdown-trigger">
|
{% if sort_by == view_model.primary_key %}
|
||||||
<div class="navbar-item has-dropdown" aria-haspopup="true"
|
{% if sort_order == "Asc" %}
|
||||||
aria-controls="dropdown-menu4">
|
<i class="ml-1 fa-solid fa-caret-up"></i>
|
||||||
<a class="navbar-link">
|
{% elif sort_order == "Desc" %}
|
||||||
<span>{{ view_model.primary_key | split(pat="_") | join(sep=" ") | title
|
<i class="ml-1 fa-solid fa-caret-down"></i>
|
||||||
}}</span>
|
{% endif %}
|
||||||
</a>
|
{% endif %}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown-menu" id="dropdown-menu4" role="menu">
|
|
||||||
<div class="dropdown-content">
|
|
||||||
<div class="dropdown-item is-clickable"
|
|
||||||
onclick="sort_by('{{ view_model.primary_key }}', 'Desc');">
|
|
||||||
Sort by Desc <i class="ml-1 fa-solid fa-caret-down"></i>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown-item is-clickable"
|
|
||||||
onclick="sort_by('{{ view_model.primary_key }}', 'Asc');">
|
|
||||||
Sort by Asc <i class="ml-1 fa-solid fa-caret-up"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</th>
|
</th>
|
||||||
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) |
|
{% for model_field in view_model.fields | filter(attribute="list_hide_column", value=false) |
|
||||||
sort(attribute="list_sort_position") -%}
|
sort(attribute="list_sort_position") -%}
|
||||||
<th>
|
<th onclick="sort_by('{{ model_field.field_name }}');" class="is-clickable">{{
|
||||||
<div class="dropdown is-hoverable">
|
model_field.field_name | split(pat="_") | join(sep=" ") | title }}
|
||||||
<div class="dropdown-trigger">
|
{% if sort_by == model_field.field_name %}
|
||||||
<div class="navbar-item has-dropdown" aria-haspopup="true"
|
{% if sort_order == "Asc" %}
|
||||||
aria-controls="dropdown-menu4">
|
<i class="ml-1 fa-solid fa-caret-up"></i>
|
||||||
<a class="navbar-link">
|
{% elif sort_order == "Desc" %}
|
||||||
<span>{{ model_field.field_name | split(pat="_") | join(sep=" ") | title
|
<i class="ml-1 fa-solid fa-caret-down"></i>
|
||||||
}}</span>
|
{% endif %}
|
||||||
</a>
|
{% endif %}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown-menu" id="dropdown-menu4" role="menu">
|
|
||||||
<div class="dropdown-content">
|
|
||||||
<div class="dropdown-item is-clickable"
|
|
||||||
onclick="sort_by('{{ model_field.field_name }}', 'Desc');">
|
|
||||||
Sort by Desc <i class="ml-1 fa-solid fa-caret-down"></i>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown-item is-clickable"
|
|
||||||
onclick="sort_by('{{ model_field.field_name }}', 'Asc');">
|
|
||||||
Sort by Asc <i class="ml-1 fa-solid fa-caret-up"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</th>
|
</th>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
<th>
|
<th>
|
||||||
@ -164,7 +134,7 @@
|
|||||||
<td>{{ entity.values | get(key=model_field.field_name) }}</td>
|
<td>{{ entity.values | get(key=model_field.field_name) }}</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
<td>
|
<td class="has-text-right">
|
||||||
<a hx-target="body" href="/admin/{{ entity_name }}/edit/{{ entity.primary_key }}" hx-vals='{
|
<a hx-target="body" href="/admin/{{ entity_name }}/edit/{{ entity.primary_key }}" hx-vals='{
|
||||||
"page" : "{{ page }}",
|
"page" : "{{ page }}",
|
||||||
"entities_per_page" : "{{ entities_per_page }}",
|
"entities_per_page" : "{{ entities_per_page }}",
|
||||||
|
Loading…
Reference in New Issue
Block a user