feat(web): add users active search
parent
fce301080c
commit
6c8183c1e3
|
@ -4,6 +4,7 @@ use axum::{
|
|||
http::HeaderMap,
|
||||
routing::{delete, get},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
server::{
|
||||
|
@ -22,24 +23,46 @@ pub fn router(ctx: Context) -> Router<Context> {
|
|||
))
|
||||
}
|
||||
|
||||
pub async fn get_users(
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct UserFilter {
|
||||
username: Option<String>,
|
||||
}
|
||||
|
||||
impl From<UserFilter> for gpodder::UserFilter {
|
||||
fn from(value: UserFilter) -> Self {
|
||||
Self {
|
||||
username: value.username,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToQuery for UserFilter {
|
||||
fn to_query(self) -> crate::web::Query {
|
||||
crate::web::Query::default().opt_parameter("username", self.username)
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_users(
|
||||
State(ctx): State<Context>,
|
||||
headers: HeaderMap,
|
||||
Extension(session): Extension<gpodder::Session>,
|
||||
Query(page): Query<super::Pagination>,
|
||||
Query(filter): Query<UserFilter>,
|
||||
) -> AppResult<TemplateResponse<Page<View>>> {
|
||||
let next_page = page.next_page();
|
||||
let filter_clone = filter.clone();
|
||||
|
||||
let user_id = session.user.id;
|
||||
let users = tokio::task::spawn_blocking(move || {
|
||||
ctx.store
|
||||
.admin(&session.user)?
|
||||
.paginated_users(page.into(), &gpodder::UserFilter::default())
|
||||
.paginated_users(page.into(), &filter.into())
|
||||
})
|
||||
.await
|
||||
.unwrap()?;
|
||||
|
||||
let next_page_query =
|
||||
(users.len() == next_page.per_page as usize).then_some(next_page.to_query());
|
||||
let next_page_query = (users.len() == next_page.per_page as usize)
|
||||
.then_some(next_page.to_query().join(filter_clone));
|
||||
|
||||
Ok(View::Users(users, user_id, next_page_query)
|
||||
.page(&headers)
|
||||
|
|
|
@ -23,6 +23,15 @@ impl Query {
|
|||
|
||||
self
|
||||
}
|
||||
|
||||
/// Convenience method for adding possibly empty parameter values from options
|
||||
pub fn opt_parameter(self, key: impl ToString, value: Option<impl ToString>) -> Self {
|
||||
if let Some(value) = value {
|
||||
self.parameter(key, value)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows objects to be converted into queries
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
<h1>Users</h1>
|
||||
|
||||
<table>
|
||||
<input
|
||||
type="text" id="username" name="username"
|
||||
hx-get="/users"
|
||||
hx-target="#users > tbody"
|
||||
hx-swap="innerHTML"
|
||||
hx-select="table > tbody > tr"
|
||||
hx-trigger="input changed delay:500ms"
|
||||
placeholder="Search..."
|
||||
/>
|
||||
<table id="users">
|
||||
<thead>
|
||||
<th>Username</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
{%- for user in users %}
|
||||
<tr>
|
||||
<th>{{ user.username }}</th>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor -%}
|
||||
|
||||
{%- if next_page_query %}
|
||||
<tr
|
||||
|
|
Loading…
Reference in New Issue