implement htmx multi select for delete

This commit is contained in:
Manuel Gugger 2022-07-31 17:11:58 +02:00
parent a8ae8eff55
commit d0cc19d65c
6 changed files with 103 additions and 71 deletions

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use crate::prelude::*; use crate::prelude::*;
use crate::routes::{create_get, create_post, delete_post, edit_get, edit_post, index, list}; use crate::routes::{create_get, create_post, delete_post, delete_many_post, edit_get, edit_post, index, list};
pub struct ActixAdminBuilder { pub struct ActixAdminBuilder {
pub scopes: Vec<actix_web::Scope>, pub scopes: Vec<actix_web::Scope>,
@ -43,6 +43,7 @@ impl ActixAdminBuilderTrait for ActixAdminBuilder {
.route("/edit/{id}", web::get().to(edit_get::<T, E>)) .route("/edit/{id}", web::get().to(edit_get::<T, E>))
.route("/edit/{id}", web::post().to(edit_post::<T, E>)) .route("/edit/{id}", web::post().to(edit_post::<T, E>))
.route("/delete/{id}", web::post().to(delete_post::<T, E>)) .route("/delete/{id}", web::post().to(delete_post::<T, E>))
.route("/delete_many", web::post().to(delete_many_post::<T, E>))
); );
self.actix_admin.entity_names.push(E::get_entity_name()); self.actix_admin.entity_names.push(E::get_entity_name());

View File

@ -0,0 +1,21 @@
use actix_web::{web, Error, HttpRequest, HttpResponse};
use serde::{Deserialize};
use actix_web::http::header;
use crate::prelude::*;
pub async fn delete_many_post<T: ActixAdminAppDataTrait, 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();
println!("{:?}", text);
Ok(HttpResponse::Found()
.append_header((
header::LOCATION,
format!("/admin/{}/list?render_partial=true", entity_name),
))
.finish())
}

View File

@ -9,11 +9,7 @@ pub async fn delete_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>
id: web::Path<i32> id: web::Path<i32>
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let db = &data.get_db(); 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();
// TODO:handle any errors
let _result = E::delete_entity(db, id.into_inner()).await; let _result = E::delete_entity(db, id.into_inner()).await;
Ok(HttpResponse::Ok() Ok(HttpResponse::Ok()

View File

@ -52,6 +52,7 @@ pub async fn list<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
ctx.insert("render_partial", &render_partial); ctx.insert("render_partial", &render_partial);
ctx.insert("num_pages", &num_pages); ctx.insert("num_pages", &num_pages);
ctx.insert("view_model", &view_model); ctx.insert("view_model", &view_model);
ctx.insert("search", &search);
let body = TERA let body = TERA
.render("list.html", &ctx) .render("list.html", &ctx)

View File

@ -10,9 +10,12 @@ mod list;
pub use list::list; pub use list::list;
mod delete_post; mod delete_post;
mod delete_many_post;
pub use delete_post::delete_post; pub use delete_post::delete_post;
pub use delete_many_post::delete_many_post;
mod edit_get; mod edit_get;
mod edit_post; mod edit_post;
pub use edit_get::edit_get; pub use edit_get::edit_get;
pub use edit_post::edit_post; pub use edit_post::edit_post;

View File

@ -5,27 +5,29 @@
{% if not render_partial or render_partial == false %} {% if not render_partial or render_partial == false %}
<article> <article>
<div class="grid"> <div class="grid">
<div> <div hx-include="#checked-rows" hx-target="#{{ entity_name }}table">
<details role="list"> <details role="list">
<summary aria-haspopup="listbox" role="button"> <summary aria-haspopup="listbox" role="button">
Actions Actions
</summary> </summary>
<ul role="listbox"> <ul role="listbox">
<li><a href="create">Create</a></li> <li><a href="create">Create</a></li>
<li><a>Delete Selected</a></li> <li><a href="#" hx-post="delete_many">Delete Selected</a></li>
</ul> </ul>
</details> </details>
</div> </div>
<div> <div>
<input type="search" id="search" name="search" placeholder="Search" <input type="search" id="search" value="{{ search }}" name="search" placeholder="Search"
hx-get="/admin/{{ entity_name }}/list?render_partial=true&entities_per_page={{ entities_per_page }}&page={{ page }}" hx-get="/admin/{{ entity_name }}/list?render_partial=true&entities_per_page={{ entities_per_page }}&page={{ page }}"
hx-trigger="keyup changed delay:500ms, search" hx-target="#{{ entity_name }}table" hx-trigger="keyup changed delay:500ms, search" hx-target="#{{ entity_name }}table"
hx-indicator=".htmx-indicator" hx-indicator=".htmx-indicator">
>
</div> </div>
</div> </div>
<figure id="{{ entity_name }}table"> {% endif %}
{% endif %}
<div id="{{ entity_name }}table">
<figure>
<form id="checked-rows">
<table role="grid"> <table role="grid">
<thead> <thead>
<tr> <tr>
@ -45,14 +47,14 @@
<tbody hx-confirm="Are you sure?" hx-target="closest tr" hx-swap="outerHTML"> <tbody hx-confirm="Are you sure?" hx-target="closest tr" hx-swap="outerHTML">
{% for entity in entities -%} {% for entity in entities -%}
<tr> <tr>
<td><input type="checkbox" id="entity{{ entity.primary_key }}" name="terms"></td> <td><input type="checkbox" name="ids" value="{{ entity.primary_key }}" name="terms"></td>
<td>{{ entity.primary_key }}</td> <td>{{ entity.primary_key }}</td>
{% for model_field in view_model.fields -%} {% for model_field in view_model.fields -%}
<td>{{ entity.values | get(key=model_field.field_name) }}</td> <td>{{ entity.values | get(key=model_field.field_name) }}</td>
{%- endfor %} {%- endfor %}
<td> <td>
<a href="edit/{{ entity.primary_key }}">&#9998;</a> <a href="edit/{{ entity.primary_key }}">&#9998;</a>
<a href="#" hx-post="delete/{{ entity.primary_key }}">&#128465;</a> <a hx-post="delete/{{ entity.primary_key }}">&#128465;</a>
</td> </td>
</tr> </tr>
{%- endfor %} {%- endfor %}
@ -60,16 +62,19 @@
<tfoot> <tfoot>
<tr> <tr>
<td colspan="{{ view_model.fields | length + 3 }}"> <td colspan="{{ view_model.fields | length + 3 }}">
<a href="?page={{ page - 1 }}&entities_per_page={{ entities_per_page }}">&laquo;</a> <a
href="?page={{ page - 1 }}&entities_per_page={{ entities_per_page }}&search={{ search }}">&laquo;</a>
{% for i in range(end=num_pages) %} {% for i in range(end=num_pages) %}
<a href="?page={{ i + 1 }}&entities_per_page={{ entities_per_page }}">{{ i + 1 }}</a> <a href="?page={{ i + 1 }}&entities_per_page={{ entities_per_page }}&search={{ search }}">{{
i + 1 }}</a>
{%- endfor %} {%- endfor %}
<a href="?page={{ page + 1 }}&entities_per_page={{ entities_per_page }}">&raquo;</a> <a
href="?page={{ page + 1 }}&entities_per_page={{ entities_per_page }}&search={{ search }}">&raquo;</a>
</td> </td>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
{% if not render_partial or render_partial == false %} </form>
</figure> </figure>
<div class="grid"> <div class="grid">
<div></div> <div></div>
@ -77,6 +82,7 @@
<div></div> <div></div>
<div> <div>
<form> <form>
<input type="hidden" value="{{ search }}" name="search">
<label for="entities_per_page">Entities per Page <label for="entities_per_page">Entities per Page
<select name="entities_per_page" onchange="this.form.submit()"> <select name="entities_per_page" onchange="this.form.submit()">
{% for a in [10,20,50,100,] %} {% for a in [10,20,50,100,] %}
@ -87,6 +93,10 @@
</form> </form>
</div> </div>
</div> </div>
</div>
{% if not render_partial or render_partial == false %}
</article> </article>
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}