use serde::Serialize;
use super::PrototypeAdminState;
use super::ResourcePerms;
use super::format_datetime;
use super::handle_list::resolve_columns;
use crate::admin::helper::resource_entry::{ListParams, ResourceEntry, SortDir};
use crate::auth::session::CurrentUser;
use crate::utils::aliases::{ADb, StrMap};
#[derive(Serialize)]
pub(super) struct InlineList {
pub key: String,
pub title: String,
pub base: String,
pub can_create: bool,
pub can_update: bool,
pub can_delete: bool,
pub columns: Vec<String>,
pub column_labels: StrMap,
pub rows: Vec<serde_json::Value>,
}
pub(super) async fn build_inlines(
db: ADb,
state: &PrototypeAdminState,
parent_entry: &ResourceEntry,
parent_id: &str,
current_user: &CurrentUser,
) -> Vec<InlineList> {
let prefix = state.config.prefix.trim_end_matches('/');
let mut inlines = Vec::new();
for child in state.registry.all() {
let Some(scope) = &child.meta.parent_scope else {
continue;
};
if scope.parent_key != parent_entry.meta.key {
continue;
}
if !current_user.is_superuser && !current_user.can_access_resource(child.meta.key) {
continue;
}
let Some(list_fn) = &child.list_fn else {
continue;
};
let params = ListParams {
offset: 0,
limit: 500,
sort_by: None,
sort_dir: SortDir::Asc,
search: None,
column_filters: Vec::new(),
scope: Some((scope.fk_col.to_string(), parent_id.to_string())),
};
let mut rows = match list_fn(db.clone(), params).await {
Ok(rows) => rows,
Err(e) => {
if let Some(level) = crate::utils::runique_log::get_log()
.admin
.as_ref()
.and_then(|a| a.list)
{
crate::runique_log!(
level,
resource = child.meta.key,
error = %e,
"inline list_fn failed — sub-list omitted"
);
}
continue;
}
};
crate::admin::helper::resolve_fk_labels(&db, &mut rows, &child.meta.fk_display).await;
if let Some(apply_enum_labels) = child.enum_label_fn {
for row in &mut rows {
apply_enum_labels(row);
}
}
if scope.local_key.is_some() {
for row in &mut rows {
if let Some(id_str) = row.get("id").and_then(|v| v.as_str()) {
let local = id_str
.split_once(':')
.map_or(id_str, |(_, local)| local)
.to_string();
if let serde_json::Value::Object(map) = row {
map.insert("id".to_string(), serde_json::Value::String(local));
}
}
}
}
for row in &mut rows {
format_datetime(row);
}
let (mut columns, column_labels) = resolve_columns(child, &rows);
columns.retain(|c| c != scope.fk_col);
let perms = ResourcePerms::resolve(current_user, child.meta.key);
inlines.push(InlineList {
key: child.meta.key.to_string(),
title: child.meta.title.to_string(),
base: format!(
"{}/{}/{}/{}",
prefix, parent_entry.meta.key, parent_id, child.meta.key
),
can_create: perms.can_create,
can_update: perms.can_update,
can_delete: perms.can_delete,
columns,
column_labels,
rows,
});
}
inlines
}