feat: implement media listing with sorting and filtering options

This commit is contained in:
2025-11-04 05:57:04 +01:00
parent ab8eeb882e
commit eaf4c90fa8
18 changed files with 238 additions and 39 deletions

View File

@@ -0,0 +1,80 @@
use libertas_core::{error::{CoreError, CoreResult}, schema::{ListMediaOptions, SortOrder}};
use sqlx::QueryBuilder as SqlxQueryBuilder;
pub trait QueryBuilder<T> {
fn apply_options_to_query<'a>(
&self,
query: SqlxQueryBuilder<'a, sqlx::Postgres>,
options: &'a T,
) -> CoreResult<SqlxQueryBuilder<'a, sqlx::Postgres>>;
}
pub struct MediaQueryBuilder {
allowed_sort_columns: Vec<String>,
}
impl MediaQueryBuilder {
pub fn new(allowed_sort_columns: Vec<String>) -> Self {
Self {
allowed_sort_columns,
}
}
fn validate_sort_column<'a>(&self, column: &'a str) -> CoreResult<&'a str> {
if self.allowed_sort_columns.contains(&column.to_string()) {
Ok(column)
} else {
Err(CoreError::Validation(format!(
"Sorting by '{}' is not supported",
column
)))
}
}
}
impl QueryBuilder<ListMediaOptions> for MediaQueryBuilder {
fn apply_options_to_query<'a>(
&self,
mut query: SqlxQueryBuilder<'a, sqlx::Postgres>,
options: &'a ListMediaOptions,
) -> CoreResult<SqlxQueryBuilder<'a, sqlx::Postgres>> {
if let Some(filter) = &options.filter {
// In the future, you would add logic here:
// if let Some(mime) = &filter.mime_type {
// query.push(" AND mime_type = ");
// query.push_bind(mime);
// }
}
if let Some(sort) = &options.sort {
let column = self.validate_sort_column(&sort.sort_by)?;
let direction = match sort.sort_order {
SortOrder::Asc => "ASC",
SortOrder::Desc => "DESC",
};
let nulls_order = if direction == "ASC" {
"NULLS LAST"
} else {
"NULLS FIRST"
};
let order_by_clause = format!("ORDER BY {} {} {}", column, direction, nulls_order);
query.push(order_by_clause);
} else {
query.push("ORDER BY date_taken DESC NULLS FIRST");
}
// --- 3. Apply Pagination (Future-Proofing Stub) ---
// if let Some(pagination) = &options.pagination {
// query.push(" LIMIT ");
// query.push_bind(pagination.limit);
// query.push(" OFFSET ");
// query.push_bind(pagination.offset);
// }
Ok(query)
}
}