reinhardt_admin/server/
list.rs1#[cfg(server)]
6use super::admin_auth::AdminAuthenticatedUser;
7use crate::adapters::{
8 AdminDatabase, AdminRecord, AdminSite, ColumnInfo, FilterInfo, FilterType, ListResponse,
9 ModelAdmin,
10};
11#[cfg(server)]
12use crate::core::{AdminDatabaseKey, AdminSiteKey};
13#[cfg(server)]
14use reinhardt_db::orm::{Filter, FilterCondition, FilterOperator, FilterValue};
15#[cfg(server)]
16use reinhardt_di::Depends;
17use reinhardt_pages::server_fn::{ServerFnError, server_fn};
18use std::sync::Arc;
19
20#[cfg(server)]
21use super::error::MapServerFnError;
22#[cfg(server)]
23use super::limits::MAX_PAGE_SIZE;
24#[cfg(server)]
25use crate::server::type_inference::{
26 get_field_metadata, infer_admin_field_type, infer_filter_type,
27};
28#[cfg(server)]
29use reinhardt_utils::utils_core::text::humanize_field_name;
30
31#[cfg(server)]
32fn build_filters(model_admin: &Arc<dyn ModelAdmin>) -> Vec<FilterInfo> {
33 let table_name = model_admin.table_name();
34 model_admin
35 .list_filter()
36 .iter()
37 .map(|field| {
38 let filter_type = get_field_metadata(table_name, field)
40 .map(|meta| {
41 let admin_type = infer_admin_field_type(&meta.field_type);
42 infer_filter_type(&admin_type)
43 })
44 .unwrap_or(FilterType::Boolean);
45
46 FilterInfo {
47 field: field.to_string(),
48 title: humanize_field_name(field),
49 filter_type,
50 current_value: None,
51 }
52 })
53 .collect()
54}
55
56#[cfg(server)]
57fn build_columns(model_admin: &Arc<dyn ModelAdmin>) -> Vec<ColumnInfo> {
58 model_admin
59 .list_display()
60 .iter()
61 .map(|field| ColumnInfo {
62 field: field.to_string(),
63 label: humanize_field_name(field),
64 sortable: true,
65 })
66 .collect()
67}
68
69#[server_fn]
103pub async fn get_list(
104 model_name: String,
105 params: crate::adapters::ListQueryParams,
106 #[inject] site: Depends<AdminSiteKey, AdminSite>,
107 #[inject] db: Depends<AdminDatabaseKey, AdminDatabase>,
108 #[inject] AdminAuthenticatedUser(user): AdminAuthenticatedUser,
109) -> Result<crate::adapters::ListResponse, ServerFnError> {
110 let model_admin = site.get_model_admin(&model_name).map_server_fn_error()?;
112 if !model_admin.has_view_permission(user.as_ref()).await {
113 return Err(ServerFnError::server(403, "Permission denied"));
114 }
115
116 let mut filter_condition: Option<FilterCondition> = None;
118 if let Some(search) = params.search.as_ref() {
119 let search_fields = model_admin.search_fields();
120 if !search_fields.is_empty() && !search.is_empty() {
121 let search_filters: Vec<FilterCondition> = search_fields
122 .iter()
123 .map(|field| {
124 FilterCondition::Single(Filter::new(
125 field.to_string(),
126 FilterOperator::Contains,
127 FilterValue::String(search.clone()),
128 ))
129 })
130 .collect();
131
132 if !search_filters.is_empty() {
133 filter_condition = Some(FilterCondition::Or(search_filters));
134 }
135 }
136 }
137
138 let allowed_filter_fields = model_admin.list_filter();
141 let mut additional_filters = Vec::new();
142 for (field, value) in params.filters.iter() {
143 if !allowed_filter_fields.contains(&field.as_str()) {
144 return Err(ServerFnError::server(
145 400,
146 format!(
147 "Unknown filter field '{}'. Allowed filter fields: {:?}",
148 field, allowed_filter_fields
149 ),
150 ));
151 }
152 additional_filters.push(Filter::new(
153 field.clone(),
154 FilterOperator::Eq,
155 FilterValue::String(value.clone()),
156 ));
157 }
158
159 let sort_by = params
161 .sort_by
162 .as_deref()
163 .or_else(|| model_admin.ordering().first().copied());
164
165 if let Some(sort_field) = sort_by {
167 let raw_field = sort_field.strip_prefix('-').unwrap_or(sort_field);
168 let allowed_sort_fields = model_admin.list_display();
169 if !allowed_sort_fields.contains(&raw_field) {
170 return Err(ServerFnError::server(
171 400,
172 format!(
173 "Unknown sort field '{}'. Allowed sort fields: {:?}",
174 raw_field, allowed_sort_fields
175 ),
176 ));
177 }
178 }
179
180 let page = params.page.unwrap_or(1).max(1); let page_size = params
183 .page_size
184 .unwrap_or_else(|| {
185 let admin_settings = crate::settings::get_admin_settings();
186 model_admin
187 .list_per_page()
188 .unwrap_or(admin_settings.list_per_page) as u64
189 })
190 .min(MAX_PAGE_SIZE); let offset = (page - 1) * page_size;
192
193 let (results, count) = db
195 .list_with_condition_and_count::<AdminRecord>(
196 model_admin.table_name(),
197 filter_condition.as_ref(),
198 additional_filters,
199 sort_by,
200 offset,
201 page_size,
202 )
203 .await
204 .map_server_fn_error()?;
205
206 let total_pages = if count > 0 {
208 count.div_ceil(page_size)
209 } else {
210 1
211 };
212
213 Ok(ListResponse {
214 model_name,
215 count,
216 page,
217 page_size,
218 total_pages,
219 results,
220 available_filters: Some(build_filters(&model_admin)),
221 columns: Some(build_columns(&model_admin)),
222 })
223}