1use std::collections::HashMap;
2use std::str::FromStr;
3
4use sea_orm::{DatabaseConnection, EntityTrait, FromQueryResult, PaginatorTrait, QueryOrder, Select};
5use serde::{Deserialize, Serialize};
6
7use crate::cutil::extract::Extract;
8use crate::cutil::meta::R;
9use crate::cutil::paged::Paged;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct Pos {
13 pub page_index: u64,
14 pub page_size: u64,
15 pub sort_direction: String,
16 pub sort_properties: Vec<String>,
17}
18
19impl Pos {
20 pub fn default() -> Self {
21 Pos {
22 page_index: 0,
23 page_size: 10,
24 sort_direction: "desc".to_string(),
25 sort_properties: vec![],
26 }
27 }
28 pub fn first() -> Self {
29 Pos {
30 page_index: 0,
31 page_size: 1,
32 sort_direction: "desc".to_string(),
33 sort_properties: vec![],
34 }
35 }
36
37 pub fn new(page_index: u64, page_size: u64, sort_direction: String, sort_properties: Vec<String>) -> Self {
38 Pos {
39 page_index,
40 page_size,
41 sort_direction,
42 sort_properties,
43 }
44 }
45 pub fn from(params: HashMap<String, String>) -> Self {
46 let page_index = params.extract_u64_default("page_index", 0);
47 let page_size = params.extract_u64_default("page_size", 10);
48 let sort_direction = params.extract_string_default("sort_direction", "desc");
49 let sort_properties: Vec<String> = params.extract_vec("sort_properties");
50
51 Pos {
52 page_index,
53 page_size,
54 sort_direction,
55 sort_properties,
56 }
57 }
58
59 pub async fn paged<M, E, D>(&self, conn: &DatabaseConnection, mut query: Select<E>) -> R<Paged<D>>
60 where
61 M: FromQueryResult + Send + Sync,
62 E: EntityTrait,
63 D: FromQueryResult + Send + Sync,
64 {
65 for property in &self.sort_properties {
66 if let Ok(column) = E::Column::from_str(property) {
67 query = match self.sort_direction.to_lowercase().as_str() {
68 "asc" => query.order_by_asc(column),
69 _ => query.order_by_desc(column),
70 };
71 }
72 }
73 let page_size = if self.page_size == 0 { 1 } else { self.page_size };
74 let query = query.into_model::<D>();
75 let paginator = query.paginate(conn, page_size);
76
77 let items: Vec<D> = paginator.fetch_page(self.page_index).await?;
78
79 let num = paginator.num_items_and_pages().await?;
80
81 let paged = Paged {
82 page_index: self.page_index,
83 page_size,
84 page_count: num.number_of_pages,
85 items,
86 item_count: num.number_of_items,
87 };
88 Ok(paged)
89 }
90}