refactor: reuse ListQuery for timeline page
Replace the hand-rolled TimelineQuery struct with the shared ListQuery type and its into_request_and_search_with_default method.
This commit is contained in:
parent
a1aefda860
commit
9d25873243
1 changed files with 5 additions and 56 deletions
|
|
@ -2,13 +2,12 @@ use axum::extract::{Query, State};
|
|||
use axum::http::HeaderMap;
|
||||
use axum::http::StatusCode;
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::application::errors::{AppError, map_app_error};
|
||||
use crate::application::routes::render_html;
|
||||
use crate::application::routes::support::{is_datastar_request, normalize_request};
|
||||
use crate::application::routes::support::{ListQuery, is_datastar_request, normalize_request};
|
||||
use crate::application::state::AppState;
|
||||
use crate::domain::listing::{ListRequest, PageSize, SortDirection, SortKey};
|
||||
use crate::domain::listing::ListRequest;
|
||||
use crate::domain::timeline::{TimelineEvent, TimelineSortKey};
|
||||
use crate::presentation::web::templates::{TimelineChunkTemplate, TimelineTemplate};
|
||||
use crate::presentation::web::views::{
|
||||
|
|
@ -19,65 +18,15 @@ const TIMELINE_PAGE_PATH: &str = "/timeline";
|
|||
const TIMELINE_FRAGMENT_PATH: &str = "/timeline";
|
||||
const TIMELINE_DEFAULT_PAGE_SIZE: u32 = 20;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum PageSizeParam {
|
||||
Number(u32),
|
||||
Text(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct TimelineQuery {
|
||||
page: Option<u32>,
|
||||
#[serde(default)]
|
||||
page_size: Option<PageSizeParam>,
|
||||
#[serde(default, rename = "sort")]
|
||||
sort_key: Option<String>,
|
||||
#[serde(default, rename = "dir")]
|
||||
sort_dir: Option<String>,
|
||||
}
|
||||
|
||||
impl TimelineQuery {
|
||||
fn to_request(&self) -> ListRequest<TimelineSortKey> {
|
||||
let page = self.page.unwrap_or(1);
|
||||
let page_size = match &self.page_size {
|
||||
Some(PageSizeParam::Number(value)) => PageSize::limited(*value),
|
||||
Some(PageSizeParam::Text(text)) if text.eq_ignore_ascii_case("all") => PageSize::All,
|
||||
Some(PageSizeParam::Text(text)) => text
|
||||
.parse::<u32>()
|
||||
.map(PageSize::limited)
|
||||
.unwrap_or(PageSize::limited(TIMELINE_DEFAULT_PAGE_SIZE)),
|
||||
None => PageSize::limited(TIMELINE_DEFAULT_PAGE_SIZE),
|
||||
};
|
||||
|
||||
let sort_key = self
|
||||
.sort_key
|
||||
.as_deref()
|
||||
.and_then(TimelineSortKey::from_query)
|
||||
.unwrap_or_else(TimelineSortKey::default);
|
||||
|
||||
let sort_direction = self
|
||||
.sort_dir
|
||||
.as_deref()
|
||||
.and_then(|dir| match dir.to_ascii_lowercase().as_str() {
|
||||
"asc" => Some(SortDirection::Asc),
|
||||
"desc" => Some(SortDirection::Desc),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| sort_key.default_direction());
|
||||
|
||||
ListRequest::new(page, page_size, sort_key, sort_direction)
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(state, cookies, headers, query))]
|
||||
pub(crate) async fn timeline_page(
|
||||
State(state): State<AppState>,
|
||||
cookies: tower_cookies::Cookies,
|
||||
headers: HeaderMap,
|
||||
Query(query): Query<TimelineQuery>,
|
||||
Query(query): Query<ListQuery>,
|
||||
) -> Result<Response, StatusCode> {
|
||||
let request = query.to_request();
|
||||
let (request, _search) =
|
||||
query.into_request_and_search_with_default::<TimelineSortKey>(TIMELINE_DEFAULT_PAGE_SIZE);
|
||||
let is_authenticated = crate::application::routes::is_authenticated(&state, &cookies).await;
|
||||
|
||||
if is_datastar_request(&headers) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue