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.
|
/// Lists all books matching the optional query filters.
|
||||||
///
|
///
|
||||||
/// Results are ordered by ID in descending order (newest first).
|
/// 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()
|
Entity::find()
|
||||||
.order_by_desc(Column::Id)
|
.order_by_desc(Column::Id)
|
||||||
.all(&self.state.db)
|
.all(&self.state.db)
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
use crate::models::book;
|
use crate::models::book;
|
||||||
use crate::routes::book::BookForm;
|
use crate::routes::book::BookForm;
|
||||||
|
use crate::routes::user::IndexQuery;
|
||||||
use crate::routes::user::UserForm;
|
use crate::routes::user::UserForm;
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
use crate::state::error::UserSnafu;
|
use crate::state::error::UserSnafu;
|
||||||
use sea_orm::ActiveValue::Set;
|
use sea_orm::ActiveValue::Set;
|
||||||
|
use sea_orm::Condition;
|
||||||
use sea_orm::DeleteResult;
|
use sea_orm::DeleteResult;
|
||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use snafu::ResultExt;
|
use snafu::ResultExt;
|
||||||
@ -53,10 +55,23 @@ impl UserOperator {
|
|||||||
Self { state }
|
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)
|
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> {
|
pub async fn find_by_id(&self, id: i32) -> Result<Model, UserError> {
|
||||||
let user: Option<Model> = Entity::find_by_id(id)
|
let user: Option<Model> = Entity::find_by_id(id)
|
||||||
.one(&self.state.db)
|
.one(&self.state.db)
|
||||||
|
|||||||
@ -66,7 +66,7 @@ pub async fn index(
|
|||||||
|
|
||||||
// Get all Users
|
// Get all Users
|
||||||
let users = UserOperator::new(state.clone())
|
let users = UserOperator::new(state.clone())
|
||||||
.list()
|
.all()
|
||||||
.await
|
.await
|
||||||
.context(UserSnafu)?;
|
.context(UserSnafu)?;
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ struct NewBookTemplate {
|
|||||||
pub async fn new(
|
pub async fn new(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
) -> 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 })
|
Ok(NewBookTemplate { users })
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ pub async fn edit(
|
|||||||
Path(id): Path<i32>,
|
Path(id): Path<i32>,
|
||||||
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
||||||
let users = UserOperator::new(state.clone())
|
let users = UserOperator::new(state.clone())
|
||||||
.list()
|
.all()
|
||||||
.await
|
.await
|
||||||
.context(UserSnafu)?;
|
.context(UserSnafu)?;
|
||||||
let book = BookOperator::new(state)
|
let book = BookOperator::new(state)
|
||||||
|
|||||||
@ -4,10 +4,11 @@ use askama::Template;
|
|||||||
use askama_web::WebTemplate;
|
use askama_web::WebTemplate;
|
||||||
use axum::{
|
use axum::{
|
||||||
Form,
|
Form,
|
||||||
extract::{Path, State},
|
extract::{Path, Query, State},
|
||||||
response::Redirect,
|
response::Redirect,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use serde_with::{NoneAsEmptyString, serde_as};
|
||||||
use snafu::prelude::*;
|
use snafu::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -25,6 +26,7 @@ use crate::{
|
|||||||
#[template(path = "users/index.html")]
|
#[template(path = "users/index.html")]
|
||||||
struct UsersIndexTemplate {
|
struct UsersIndexTemplate {
|
||||||
user_with_books_number: Vec<UserWithBookNumber>,
|
user_with_books_number: Vec<UserWithBookNumber>,
|
||||||
|
query: IndexQuery,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UserWithBookNumber {
|
pub struct UserWithBookNumber {
|
||||||
@ -36,16 +38,25 @@ pub struct UserWithBookNumber {
|
|||||||
pub borrowed_book_number: usize,
|
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(
|
pub async fn index(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
|
Query(query): Query<IndexQuery>,
|
||||||
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
) -> Result<impl axum::response::IntoResponse, AppStateError> {
|
||||||
let users = UserOperator::new(state.clone())
|
let users = UserOperator::new(state.clone())
|
||||||
.list()
|
.all_filtered(query.clone())
|
||||||
.await
|
.await
|
||||||
.context(UserSnafu)?;
|
.context(UserSnafu)?;
|
||||||
|
|
||||||
let books = BookOperator::new(state.clone())
|
let books = BookOperator::new(state.clone())
|
||||||
.list()
|
.all()
|
||||||
.await
|
.await
|
||||||
.context(BookSnafu)?;
|
.context(BookSnafu)?;
|
||||||
|
|
||||||
@ -74,6 +85,7 @@ pub async fn index(
|
|||||||
|
|
||||||
Ok(UsersIndexTemplate {
|
Ok(UsersIndexTemplate {
|
||||||
user_with_books_number: result,
|
user_with_books_number: result,
|
||||||
|
query,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,30 @@
|
|||||||
<a class="btn-success btn" href="/users/new">Add User</a>
|
<a class="btn-success btn" href="/users/new">Add User</a>
|
||||||
{% endcall %}
|
{% 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() %}
|
{% call cards::card() %}
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user