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::HeaderMap;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::response::{IntoResponse, Response};
|
use axum::response::{IntoResponse, Response};
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use crate::application::errors::{AppError, map_app_error};
|
use crate::application::errors::{AppError, map_app_error};
|
||||||
use crate::application::routes::render_html;
|
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::application::state::AppState;
|
||||||
use crate::domain::listing::{ListRequest, PageSize, SortDirection, SortKey};
|
use crate::domain::listing::ListRequest;
|
||||||
use crate::domain::timeline::{TimelineEvent, TimelineSortKey};
|
use crate::domain::timeline::{TimelineEvent, TimelineSortKey};
|
||||||
use crate::presentation::web::templates::{TimelineChunkTemplate, TimelineTemplate};
|
use crate::presentation::web::templates::{TimelineChunkTemplate, TimelineTemplate};
|
||||||
use crate::presentation::web::views::{
|
use crate::presentation::web::views::{
|
||||||
|
|
@ -19,65 +18,15 @@ const TIMELINE_PAGE_PATH: &str = "/timeline";
|
||||||
const TIMELINE_FRAGMENT_PATH: &str = "/timeline";
|
const TIMELINE_FRAGMENT_PATH: &str = "/timeline";
|
||||||
const TIMELINE_DEFAULT_PAGE_SIZE: u32 = 20;
|
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))]
|
#[tracing::instrument(skip(state, cookies, headers, query))]
|
||||||
pub(crate) async fn timeline_page(
|
pub(crate) async fn timeline_page(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
cookies: tower_cookies::Cookies,
|
cookies: tower_cookies::Cookies,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
Query(query): Query<TimelineQuery>,
|
Query(query): Query<ListQuery>,
|
||||||
) -> Result<Response, StatusCode> {
|
) -> 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;
|
let is_authenticated = crate::application::routes::is_authenticated(&state, &cookies).await;
|
||||||
|
|
||||||
if is_datastar_request(&headers) {
|
if is_datastar_request(&headers) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue