feat: Add pagination support to ListMediaParams and ListMediaOptions
This commit is contained in:
@@ -1,10 +1,21 @@
|
|||||||
use axum::{extract::{FromRequestParts, Query}, http::request::Parts};
|
use axum::{
|
||||||
use libertas_core::{error::CoreError, schema::{FilterParams, ListMediaOptions, MetadataFilter, SortOrder, SortParams}};
|
extract::{FromRequestParts, Query},
|
||||||
|
http::request::Parts,
|
||||||
|
};
|
||||||
|
use libertas_core::{
|
||||||
|
error::CoreError,
|
||||||
|
schema::{
|
||||||
|
FilterParams, ListMediaOptions, MetadataFilter, PaginationParams, SortOrder, SortParams,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{error::ApiError, schema::ListMediaParams, state::AppState};
|
use crate::{error::ApiError, schema::ListMediaParams, state::AppState};
|
||||||
|
|
||||||
pub struct ApiListMediaOptions(pub ListMediaOptions);
|
pub struct ApiListMediaOptions(pub ListMediaOptions);
|
||||||
|
|
||||||
|
const DEFAULT_PAGE: u32 = 1;
|
||||||
|
const DEFAULT_LIMIT: u32 = 50;
|
||||||
|
|
||||||
impl From<ListMediaParams> for ListMediaOptions {
|
impl From<ListMediaParams> for ListMediaOptions {
|
||||||
fn from(params: ListMediaParams) -> Self {
|
fn from(params: ListMediaParams) -> Self {
|
||||||
let sort = params.sort_by.map(|field| {
|
let sort = params.sort_by.map(|field| {
|
||||||
@@ -22,24 +33,44 @@ impl From<ListMediaParams> for ListMediaOptions {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(
|
Some(
|
||||||
params.metadata
|
params
|
||||||
.into_iter()
|
.metadata
|
||||||
.filter_map(|s| {
|
.into_iter()
|
||||||
s.split_once(":").map(|(key, value)| MetadataFilter {
|
.filter_map(|s| {
|
||||||
tag_name: key.to_string(),
|
s.split_once(":").map(|(key, value)| MetadataFilter {
|
||||||
tag_value: value.to_string(),
|
tag_name: key.to_string(),
|
||||||
|
tag_value: value.to_string(),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
.collect::<Vec<_>>(),
|
||||||
.collect::<Vec<_>>()
|
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let pagination = {
|
||||||
|
let page = params.page.unwrap_or(DEFAULT_PAGE);
|
||||||
|
let limit = params.limit.unwrap_or(DEFAULT_LIMIT);
|
||||||
|
|
||||||
|
let page = if page == 0 { DEFAULT_PAGE } else { page };
|
||||||
|
|
||||||
|
let limit = if limit > (DEFAULT_LIMIT * 2) {
|
||||||
|
DEFAULT_LIMIT * 2
|
||||||
|
} else {
|
||||||
|
limit
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(PaginationParams { page, limit })
|
||||||
|
};
|
||||||
|
|
||||||
let filter = Some(FilterParams {
|
let filter = Some(FilterParams {
|
||||||
mime_type: params.mime_type,
|
mime_type: params.mime_type,
|
||||||
metadata_filters,
|
metadata_filters,
|
||||||
});
|
});
|
||||||
|
|
||||||
ListMediaOptions { sort, filter }
|
ListMediaOptions {
|
||||||
|
sort,
|
||||||
|
filter,
|
||||||
|
pagination,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,4 +87,4 @@ impl FromRequestParts<AppState> for ApiListMediaOptions {
|
|||||||
|
|
||||||
Ok(ApiListMediaOptions(params.into()))
|
Ok(ApiListMediaOptions(params.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ pub struct ListMediaParams {
|
|||||||
pub mime_type: Option<String>,
|
pub mime_type: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub metadata: Vec<String>,
|
pub metadata: Vec<String>,
|
||||||
|
pub page: Option<u32>,
|
||||||
|
pub limit: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|||||||
@@ -63,11 +63,17 @@ pub struct FilterParams {
|
|||||||
// pub date_range: Option<(chrono::DateTime<chrono::Utc>, chrono::DateTime<chrono::Utc>)>,
|
// pub date_range: Option<(chrono::DateTime<chrono::Utc>, chrono::DateTime<chrono::Utc>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct PaginationParams {
|
||||||
|
pub page: u32,
|
||||||
|
pub limit: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ListMediaOptions {
|
pub struct ListMediaOptions {
|
||||||
pub sort: Option<SortParams>,
|
pub sort: Option<SortParams>,
|
||||||
pub filter: Option<FilterParams>,
|
pub filter: Option<FilterParams>,
|
||||||
// pub pagination: Option<PaginationParams>,
|
pub pagination: Option<PaginationParams>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -99,12 +99,15 @@ impl QueryBuilder<ListMediaOptions> for MediaQueryBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- 3. Apply Pagination (Future-Proofing Stub) ---
|
// --- 3. Apply Pagination (Future-Proofing Stub) ---
|
||||||
// if let Some(pagination) = &options.pagination {
|
if let Some(pagination) = &options.pagination {
|
||||||
// query.push(" LIMIT ");
|
let limit = pagination.limit as i64;
|
||||||
// query.push_bind(pagination.limit);
|
let offset = (pagination.page.saturating_sub(1) as i64) * limit;
|
||||||
// query.push(" OFFSET ");
|
|
||||||
// query.push_bind(pagination.offset);
|
query.push(" LIMIT ");
|
||||||
// }
|
query.push_bind(limit);
|
||||||
|
query.push(" OFFSET ");
|
||||||
|
query.push_bind(offset);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(query)
|
Ok(query)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user