yggdrasil/api/comments/
list.rs1use crate::api::comments::types::*;
7use crate::api::error::ApiError;
8use leptos::prelude::*;
9
10#[server(GetAllComments, endpoint = "get_all_comments", input = leptos::server_fn::codec::Json)]
15pub async fn get_all_comments(
16 page: i32,
17 status: Option<String>,
18) -> Result<AllCommentsResponse, ApiError> {
19 #[cfg(feature = "server")]
20 {
21 use crate::api::auth::get_current_admin_user;
22
23 let _admin = get_current_admin_user().await?;
24 Ok(list_admin_comments_impl(page, status).await?)
25 }
26 #[cfg(not(feature = "server"))]
27 unreachable!()
28}
29
30#[cfg(feature = "server")]
34pub(crate) async fn list_admin_comments_impl(
35 page: i32,
36 status: Option<String>,
37) -> Result<AllCommentsResponse, crate::api::error::AppError> {
38 use crate::api::comments::helpers::row_to_admin_comment;
39 use crate::api::error::AppError;
40 use crate::db::pool::get_conn;
41
42 let page = page.max(1);
43 let per_page: i64 = 20;
44 let offset: i64 = (page as i64 - 1) * per_page;
45
46 let client = get_conn().await.map_err(AppError::db_conn)?;
47
48 let status = status.filter(|s| !s.is_empty());
50 let trash = status.as_deref() == Some("trash");
51 let where_clause = if trash {
53 "c.deleted_at IS NOT NULL AND ($1::text IS NULL OR c.status = $1)"
54 } else {
55 "c.deleted_at IS NULL AND ($1::text IS NULL OR c.status = $1)"
56 };
57 let status_param: Option<&str> = if trash { None } else { status.as_deref() };
58 let total: i64 = client
59 .query_one(
60 &format!("SELECT COUNT(*) FROM comments c WHERE {where_clause}"),
61 &[&status_param],
62 )
63 .await
64 .map_err(AppError::query)?
65 .get(0);
66 let rows = client
67 .query(
68 &format!(
69 "SELECT c.id, c.post_id, c.parent_id, c.depth, c.author_name, c.author_email, \
70 c.author_url, c.content_md, c.status, c.created_at, \
71 c.user_id, u.display_name AS user_display_name, u.avatar_url AS user_avatar, \
72 COALESCE(pu.display_name, pc.author_name) AS parent_author, \
73 p.title as post_title, p.slug as post_slug \
74 FROM comments c JOIN posts p ON c.post_id = p.id \
75 LEFT JOIN users u ON c.user_id = u.id \
76 LEFT JOIN comments pc ON pc.id = c.parent_id \
77 LEFT JOIN users pu ON pc.user_id = pu.id \
78 WHERE {where_clause} \
79 ORDER BY c.created_at DESC LIMIT $2 OFFSET $3"
80 ),
81 &[&status_param, &per_page, &offset],
82 )
83 .await
84 .map_err(AppError::query)?;
85 let counts = client
86 .query_one(
87 "SELECT COUNT(*) FILTER (WHERE deleted_at IS NULL AND status = 'pending'), \
88 COUNT(*) FILTER (WHERE deleted_at IS NULL AND status = 'approved'), \
89 COUNT(*) FILTER (WHERE deleted_at IS NULL AND status = 'spam'), \
90 COUNT(*) FILTER (WHERE deleted_at IS NOT NULL) \
91 FROM comments",
92 &[],
93 )
94 .await
95 .map_err(AppError::query)?;
96 let counts = CommentCounts {
97 pending: counts.get(0),
98 approved: counts.get(1),
99 spam: counts.get(2),
100 trash: counts.get(3),
101 };
102
103 let comments = rows.iter().map(row_to_admin_comment).collect();
104
105 Ok(AllCommentsResponse {
106 comments,
107 total,
108 counts,
109 })
110}