User filtered
This commit is contained in:
parent
3b9a5800a5
commit
a4c5e8185b
@ -70,7 +70,7 @@ impl BookOperator {
|
||||
/// Lists all books matching the optional query filters.
|
||||
///
|
||||
/// Results are ordered by ID in descending order (newest first).
|
||||
pub async fn list(&self) -> Result<Vec<Model>, BookError> {
|
||||
pub async fn all(&self) -> Result<Vec<Model>, BookError> {
|
||||
Entity::find()
|
||||
.order_by_desc(Column::Id)
|
||||
.all(&self.state.db)
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use crate::models::book;
|
||||
use crate::routes::book::BookForm;
|
||||
use crate::routes::user::IndexQuery;
|
||||
use crate::routes::user::UserForm;
|
||||
use crate::state::AppState;
|
||||
use crate::state::error::UserSnafu;
|
||||
use sea_orm::ActiveValue::Set;
|
||||
use sea_orm::Condition;
|
||||
use sea_orm::DeleteResult;
|
||||
use sea_orm::entity::prelude::*;
|
||||
use snafu::ResultExt;
|
||||
@ -53,10 +55,23 @@ impl UserOperator {
|
||||
Self { state }
|
||||
}
|
||||
|
||||
pub async fn list(&self) -> Result<Vec<Model>, UserError> {
|
||||
pub async fn all(&self) -> Result<Vec<Model>, UserError> {
|
||||
Entity::find().all(&self.state.db).await.context(DBSnafu)
|
||||
}
|
||||
|
||||
pub async fn all_filtered(&self, query: IndexQuery) -> Result<Vec<Model>, UserError> {
|
||||
let mut conditions = Condition::all();
|
||||
if let Some(name) = query.name {
|
||||
conditions = conditions.add(Column::Name.contains(name))
|
||||
}
|
||||
|
||||
Entity::find()
|
||||
.filter(conditions)
|
||||
.all(&self.state.db)
|
||||
.await
|
||||
.context(DBSnafu)
|
||||
}
|
||||
|
||||
pub async fn find_by_id(&self, id: i32) -> Result<Model, UserError> {
|
||||
let user: Option<Model> = Entity::find_by_id(id)
|
||||
.one(&self.state.db)
|
||||
|
||||
@ -66,7 +66,7 @@ pub async fn index(
|
||||
|
||||
// Get all Users
|
||||
let users = UserOperator::new(state.clone())
|
||||
.list()
|
||||
.all()
|
||||
.await
|
||||
.context(UserSnafu)?;
|
||||
|
||||
@ -203,7 +203,7 @@ struct NewBookTemplate {
|
||||
pub async fn new(
|
||||
State(state): State<AppState>,
|
||||
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
||||
let users = UserOperator::new(state).list().await.context(UserSnafu)?;
|
||||
let users = UserOperator::new(state).all().await.context(UserSnafu)?;
|
||||
|
||||
Ok(NewBookTemplate { users })
|
||||
}
|
||||
@ -220,7 +220,7 @@ pub async fn edit(
|
||||
Path(id): Path<i32>,
|
||||
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
||||
let users = UserOperator::new(state.clone())
|
||||
.list()
|
||||
.all()
|
||||
.await
|
||||
.context(UserSnafu)?;
|
||||
let book = BookOperator::new(state)
|
||||
|
||||
@ -4,10 +4,11 @@ use askama::Template;
|
||||
use askama_web::WebTemplate;
|
||||
use axum::{
|
||||
Form,
|
||||
extract::{Path, State},
|
||||
extract::{Path, Query, State},
|
||||
response::Redirect,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_with::{NoneAsEmptyString, serde_as};
|
||||
use snafu::prelude::*;
|
||||
|
||||
use crate::{
|
||||
@ -25,6 +26,7 @@ use crate::{
|
||||
#[template(path = "users/index.html")]
|
||||
struct UsersIndexTemplate {
|
||||
user_with_books_number: Vec<UserWithBookNumber>,
|
||||
query: IndexQuery,
|
||||
}
|
||||
|
||||
pub struct UserWithBookNumber {
|
||||
@ -36,16 +38,25 @@ pub struct UserWithBookNumber {
|
||||
pub borrowed_book_number: usize,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct IndexQuery {
|
||||
#[serde(default)]
|
||||
#[serde_as(as = "NoneAsEmptyString")]
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn index(
|
||||
State(state): State<AppState>,
|
||||
Query(query): Query<IndexQuery>,
|
||||
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
||||
let users = UserOperator::new(state.clone())
|
||||
.list()
|
||||
.all_filtered(query.clone())
|
||||
.await
|
||||
.context(UserSnafu)?;
|
||||
|
||||
let books = BookOperator::new(state.clone())
|
||||
.list()
|
||||
.all()
|
||||
.await
|
||||
.context(BookSnafu)?;
|
||||
|
||||
@ -74,6 +85,7 @@ pub async fn index(
|
||||
|
||||
Ok(UsersIndexTemplate {
|
||||
user_with_books_number: result,
|
||||
query,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,30 @@
|
||||
<a class="btn-success btn" href="/users/new">Add User</a>
|
||||
{% endcall %}
|
||||
|
||||
{% call cards::card() %}
|
||||
<form method="get">
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<label for="name" class="form-label">Name</label>
|
||||
{% match query.name %}
|
||||
{% when Some with (value) %}
|
||||
<input type="text" name="name" value="{{ value }}" class="form-control" placeholder="Ex: Koprotkine">
|
||||
{% when None %}
|
||||
<input type="text" name="name" class="form-control" placeholder="Ex: Koprotkine">
|
||||
{% endmatch %}
|
||||
</div>
|
||||
|
||||
<div class="col-md-1 d-flex align-items-end">
|
||||
<input type="submit" value="Search" class="btn btn-info w-100">
|
||||
</div>
|
||||
|
||||
<div class="col-md-1 d-flex align-items-end">
|
||||
<a href="/users" class="btn btn-light">Reset</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endcall %}
|
||||
|
||||
{% call cards::card() %}
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user