feat: some experimentation with api filtering
parent
e684cfb84e
commit
e1642d939b
|
@ -1,5 +1,7 @@
|
||||||
mod pagination;
|
mod pagination;
|
||||||
|
|
||||||
|
use sea_orm::{sea_query::IntoCondition, *};
|
||||||
|
|
||||||
use axum::extract::{Path, Query, State};
|
use axum::extract::{Path, Query, State};
|
||||||
use axum::routing::get;
|
use axum::routing::get;
|
||||||
use axum::Json;
|
use axum::Json;
|
||||||
|
@ -7,7 +9,7 @@ use axum::Router;
|
||||||
|
|
||||||
use pagination::PaginatedResponse;
|
use pagination::PaginatedResponse;
|
||||||
|
|
||||||
use crate::db;
|
use crate::db::{self, *};
|
||||||
|
|
||||||
pub fn router() -> Router<crate::Global> {
|
pub fn router() -> Router<crate::Global> {
|
||||||
Router::new()
|
Router::new()
|
||||||
|
@ -20,16 +22,27 @@ pub fn router() -> Router<crate::Global> {
|
||||||
async fn get_repos(
|
async fn get_repos(
|
||||||
State(global): State<crate::Global>,
|
State(global): State<crate::Global>,
|
||||||
Query(pagination): Query<pagination::Query>,
|
Query(pagination): Query<pagination::Query>,
|
||||||
|
Query(filter): Query<db::query::repo::Filter>,
|
||||||
) -> crate::Result<Json<PaginatedResponse<db::repo::Model>>> {
|
) -> crate::Result<Json<PaginatedResponse<db::repo::Model>>> {
|
||||||
let (total_pages, repos) = global
|
let page = pagination.page.unwrap_or(1) - 1;
|
||||||
.db
|
let per_page = pagination.per_page.unwrap_or(25);
|
||||||
.repo
|
|
||||||
.page(
|
let paginator = Repo::find()
|
||||||
pagination.per_page.unwrap_or(25),
|
.filter(filter)
|
||||||
pagination.page.unwrap_or(1) - 1,
|
.order_by_asc(package::Column::Id)
|
||||||
)
|
.paginate(&global.db, pagination.per_page.unwrap_or(25));
|
||||||
|
let items = paginator
|
||||||
|
.fetch_page(pagination.page.unwrap_or(1) - 1)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(Json(pagination.res(total_pages, repos)))
|
let total_pages = paginator.num_pages().await?;
|
||||||
|
|
||||||
|
Ok(Json(PaginatedResponse {
|
||||||
|
page,
|
||||||
|
per_page,
|
||||||
|
total_pages,
|
||||||
|
count: items.len(),
|
||||||
|
items,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_single_repo(
|
async fn get_single_repo(
|
||||||
|
@ -49,6 +62,7 @@ async fn get_single_repo(
|
||||||
async fn get_packages(
|
async fn get_packages(
|
||||||
State(global): State<crate::Global>,
|
State(global): State<crate::Global>,
|
||||||
Query(pagination): Query<pagination::Query>,
|
Query(pagination): Query<pagination::Query>,
|
||||||
|
Query(filter): Query<db::query::package::Filter>,
|
||||||
) -> crate::Result<Json<PaginatedResponse<db::package::Model>>> {
|
) -> crate::Result<Json<PaginatedResponse<db::package::Model>>> {
|
||||||
let (total_pages, pkgs) = global
|
let (total_pages, pkgs) = global
|
||||||
.db
|
.db
|
||||||
|
@ -56,6 +70,7 @@ async fn get_packages(
|
||||||
.page(
|
.page(
|
||||||
pagination.per_page.unwrap_or(25),
|
pagination.per_page.unwrap_or(25),
|
||||||
pagination.page.unwrap_or(1) - 1,
|
pagination.page.unwrap_or(1) - 1,
|
||||||
|
filter,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub const DEFAULT_PAGE: u64 = 0;
|
pub const DEFAULT_PAGE: u64 = 1;
|
||||||
pub const DEFAULT_PER_PAGE: u64 = 25;
|
pub const DEFAULT_PER_PAGE: u64 = 25;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
mod conn;
|
mod conn;
|
||||||
pub mod entities;
|
pub mod entities;
|
||||||
mod migrator;
|
mod migrator;
|
||||||
mod query;
|
pub mod query;
|
||||||
|
|
||||||
use sea_orm::{ConnectOptions, Database, DatabaseConnection, DeriveActiveEnum, EnumIter};
|
use sea_orm::{ConnectOptions, Database, DatabaseConnection, DeriveActiveEnum, EnumIter};
|
||||||
use sea_orm_migration::MigratorTrait;
|
use sea_orm_migration::MigratorTrait;
|
||||||
|
@ -14,6 +14,7 @@ type Result<T> = std::result::Result<T, sea_orm::DbErr>;
|
||||||
|
|
||||||
#[derive(EnumIter, DeriveActiveEnum, Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
|
#[derive(EnumIter, DeriveActiveEnum, Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
|
||||||
#[sea_orm(rs_type = "i32", db_type = "Integer")]
|
#[sea_orm(rs_type = "i32", db_type = "Integer")]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum PackageRelatedEnum {
|
pub enum PackageRelatedEnum {
|
||||||
#[sea_orm(num_value = 0)]
|
#[sea_orm(num_value = 0)]
|
||||||
Conflicts,
|
Conflicts,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod package;
|
pub mod package;
|
||||||
mod repo;
|
pub mod repo;
|
||||||
|
|
||||||
pub use package::PackageQuery;
|
pub use package::PackageQuery;
|
||||||
pub use repo::RepoQuery;
|
pub use repo::RepoQuery;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use sea_orm::*;
|
use sea_orm::{sea_query::IntoCondition, *};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::db::*;
|
use crate::db::*;
|
||||||
|
|
||||||
|
@ -7,6 +8,25 @@ pub struct PackageQuery {
|
||||||
conn: DatabaseConnection,
|
conn: DatabaseConnection,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Filter {
|
||||||
|
repo: Option<i32>,
|
||||||
|
arch: Option<String>,
|
||||||
|
name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoCondition for Filter {
|
||||||
|
fn into_condition(self) -> Condition {
|
||||||
|
Condition::all()
|
||||||
|
.add_option(self.repo.map(|repo| package::Column::RepoId.eq(repo)))
|
||||||
|
.add_option(self.arch.map(|arch| package::Column::Arch.eq(arch)))
|
||||||
|
.add_option(
|
||||||
|
self.name
|
||||||
|
.map(|name| package::Column::Name.like(format!("%{}%", name))),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PackageQuery {
|
impl PackageQuery {
|
||||||
pub fn new(conn: DatabaseConnection) -> Self {
|
pub fn new(conn: DatabaseConnection) -> Self {
|
||||||
Self { conn }
|
Self { conn }
|
||||||
|
@ -16,8 +36,10 @@ impl PackageQuery {
|
||||||
&self,
|
&self,
|
||||||
per_page: u64,
|
per_page: u64,
|
||||||
page: u64,
|
page: u64,
|
||||||
|
filter: Filter,
|
||||||
) -> super::Result<(u64, Vec<package::Model>)> {
|
) -> super::Result<(u64, Vec<package::Model>)> {
|
||||||
let paginator = Package::find()
|
let paginator = Package::find()
|
||||||
|
.filter(filter)
|
||||||
.order_by_asc(package::Column::Id)
|
.order_by_asc(package::Column::Id)
|
||||||
.paginate(&self.conn, per_page);
|
.paginate(&self.conn, per_page);
|
||||||
let packages = paginator.fetch_page(page).await?;
|
let packages = paginator.fetch_page(page).await?;
|
||||||
|
@ -132,7 +154,10 @@ impl PackageQuery {
|
||||||
package_id: Set(pkg_entry.id),
|
package_id: Set(pkg_entry.id),
|
||||||
r#type: Set(t),
|
r#type: Set(t),
|
||||||
name: Set(s.to_string()),
|
name: Set(s.to_string()),
|
||||||
}));
|
}))
|
||||||
|
.on_empty_do_nothing()
|
||||||
|
.exec(&self.conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
PackageFile::insert_many(pkg.files.iter().map(|s| package_file::ActiveModel {
|
PackageFile::insert_many(pkg.files.iter().map(|s| package_file::ActiveModel {
|
||||||
package_id: Set(pkg_entry.id),
|
package_id: Set(pkg_entry.id),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use sea_orm::*;
|
use sea_orm::{sea_query::IntoCondition, *};
|
||||||
|
|
||||||
use crate::db::*;
|
use crate::db::*;
|
||||||
|
|
||||||
|
@ -7,6 +7,17 @@ pub struct RepoQuery {
|
||||||
conn: DatabaseConnection,
|
conn: DatabaseConnection,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Filter {
|
||||||
|
name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoCondition for Filter {
|
||||||
|
fn into_condition(self) -> Condition {
|
||||||
|
Condition::all().add_option(self.name.map(|name| package::Column::Name.like(name)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RepoQuery {
|
impl RepoQuery {
|
||||||
pub fn new(conn: DatabaseConnection) -> Self {
|
pub fn new(conn: DatabaseConnection) -> Self {
|
||||||
Self { conn }
|
Self { conn }
|
||||||
|
|
Loading…
Reference in New Issue