From 63490d60f0f60e0e86cf48a03e80667892e62804 Mon Sep 17 00:00:00 2001 From: dal Date: Tue, 11 Mar 2025 22:21:30 -0600 Subject: [PATCH] dashboard handler --- .../get_dashboard_handler.rs | 6 +- .../src/dashboards/list_dashboard_handler.rs | 112 ++++++++++++++++++ api/libs/handlers/src/dashboards/mod.rs | 7 ++ .../dashboard_files => dashboards}/types.rs | 8 +- .../src/files/dashboard_files/helpers/mod.rs | 3 - .../handlers/src/files/dashboard_files/mod.rs | 5 - api/libs/handlers/src/files/mod.rs | 3 - api/libs/handlers/src/lib.rs | 2 +- .../rest/routes/dashboards/get_dashboard.rs | 5 +- .../rest/routes/dashboards/list_dashboards.rs | 37 ++++++ api/src/routes/rest/routes/dashboards/mod.rs | 2 + 11 files changed, 168 insertions(+), 22 deletions(-) rename api/libs/handlers/src/{files/dashboard_files/helpers => dashboards}/get_dashboard_handler.rs (97%) create mode 100644 api/libs/handlers/src/dashboards/list_dashboard_handler.rs create mode 100644 api/libs/handlers/src/dashboards/mod.rs rename api/libs/handlers/src/{files/dashboard_files => dashboards}/types.rs (95%) delete mode 100644 api/libs/handlers/src/files/dashboard_files/helpers/mod.rs delete mode 100644 api/libs/handlers/src/files/dashboard_files/mod.rs delete mode 100644 api/libs/handlers/src/files/mod.rs create mode 100644 api/src/routes/rest/routes/dashboards/list_dashboards.rs diff --git a/api/libs/handlers/src/files/dashboard_files/helpers/get_dashboard_handler.rs b/api/libs/handlers/src/dashboards/get_dashboard_handler.rs similarity index 97% rename from api/libs/handlers/src/files/dashboard_files/helpers/get_dashboard_handler.rs rename to api/libs/handlers/src/dashboards/get_dashboard_handler.rs index ac2f9687c..a8489f16b 100644 --- a/api/libs/handlers/src/files/dashboard_files/helpers/get_dashboard_handler.rs +++ b/api/libs/handlers/src/dashboards/get_dashboard_handler.rs @@ -9,14 +9,14 @@ use futures::future::{try_join_all, join_all}; use chrono::{DateTime, Utc}; use serde_yaml; -use crate::files::dashboard_files::types::{ - BusterDashboard, BusterDashboardResponse, DashboardConfig, DashboardRow, DashboardRowItem, -}; + use crate::metrics::{get_metric_handler, BusterMetric}; use database::enums::{AssetPermissionRole, Verification}; use database::pool::get_pg_pool; use database::schema::dashboard_files; +use super::{BusterDashboard, BusterDashboardResponse, DashboardConfig, DashboardRow, DashboardRowItem}; + #[derive(Queryable, Selectable)] #[diesel(table_name = dashboard_files)] struct QueryableDashboardFile { diff --git a/api/libs/handlers/src/dashboards/list_dashboard_handler.rs b/api/libs/handlers/src/dashboards/list_dashboard_handler.rs new file mode 100644 index 000000000..c4d48c9ed --- /dev/null +++ b/api/libs/handlers/src/dashboards/list_dashboard_handler.rs @@ -0,0 +1,112 @@ +use std::collections::HashMap; + +use anyhow::{anyhow, Result}; +use diesel::{ + BoolExpressionMethods, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl, + Queryable, Selectable, +}; +use diesel_async::RunQueryDsl; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; +use chrono::{DateTime, Utc}; + +use database::{ + enums::{AssetPermissionRole, AssetType, IdentityType, Verification}, + pool::get_pg_pool, + schema::{asset_permissions, dashboard_files, users}, +}; + +use super::{BusterDashboardListItem, DashboardMember}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct DashboardsListRequest { + /// The page number to fetch + pub page_token: i64, + /// Number of items per page + pub page_size: i64, + /// Filter for dashboards shared with the current user + pub shared_with_me: Option, + /// Filter for dashboards owned by the current user + pub only_my_dashboards: Option, +} + +#[derive(Queryable, Selectable)] +#[diesel(table_name = dashboard_files)] +struct QueryableDashboardFile { + id: Uuid, + name: String, + created_by: Uuid, + created_at: DateTime, + updated_at: DateTime, +} + +pub async fn list_dashboard_handler( + user_id: &Uuid, + request: DashboardsListRequest, +) -> Result> { + let mut conn = match get_pg_pool().get().await { + Ok(conn) => conn, + Err(e) => return Err(anyhow!("Failed to get database connection: {}", e)), + }; + + // Calculate offset from page_token + let offset = request.page_token * request.page_size; + + // Build the base query + let mut dashboard_statement = dashboard_files::table + .select(( + dashboard_files::id, + dashboard_files::name, + dashboard_files::created_by, + dashboard_files::created_at, + dashboard_files::updated_at, + )) + .filter(dashboard_files::deleted_at.is_null()) + .distinct() + .order((dashboard_files::updated_at.desc(), dashboard_files::id.asc())) + .offset(offset) + .limit(request.page_size) + .into_boxed(); + + // Execute the query + let dashboard_results = match dashboard_statement + .load::<( + Uuid, + String, + Uuid, + DateTime, + DateTime, + )>(&mut conn) + .await + { + Ok(results) => results, + Err(e) => return Err(anyhow!("Error getting dashboard results: {}", e)), + }; + + // Transform query results into BusterDashboardListItem + let dashboards = dashboard_results + .into_iter() + .map( + |(id, name, created_by, created_at, updated_at)| { + let owner = DashboardMember { + id: created_by, + name: "Unknown".to_string(), + avatar_url: None, + }; + + BusterDashboardListItem { + id, + name, + created_at, + last_edited: updated_at, + owner, + members: vec![], + status: Verification::Verified, // Default status, can be updated if needed + is_shared: false, + } + }, + ) + .collect(); + + Ok(dashboards) +} diff --git a/api/libs/handlers/src/dashboards/mod.rs b/api/libs/handlers/src/dashboards/mod.rs new file mode 100644 index 000000000..212a6b4d9 --- /dev/null +++ b/api/libs/handlers/src/dashboards/mod.rs @@ -0,0 +1,7 @@ +mod get_dashboard_handler; +mod list_dashboard_handler; +mod types; + +pub use get_dashboard_handler::*; +pub use list_dashboard_handler::*; +pub use types::*; \ No newline at end of file diff --git a/api/libs/handlers/src/files/dashboard_files/types.rs b/api/libs/handlers/src/dashboards/types.rs similarity index 95% rename from api/libs/handlers/src/files/dashboard_files/types.rs rename to api/libs/handlers/src/dashboards/types.rs index bfd305c24..c7dda2f42 100644 --- a/api/libs/handlers/src/files/dashboard_files/types.rs +++ b/api/libs/handlers/src/dashboards/types.rs @@ -9,9 +9,9 @@ use crate::metrics::types::BusterMetric; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct BusterDashboardListItem { - pub created_at: String, - pub id: String, - pub last_edited: String, + pub created_at: DateTime, + pub id: Uuid, + pub last_edited: DateTime, pub members: Vec, pub name: String, pub owner: DashboardMember, @@ -22,7 +22,7 @@ pub struct BusterDashboardListItem { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct DashboardMember { pub avatar_url: Option, - pub id: String, + pub id: Uuid, pub name: String, } diff --git a/api/libs/handlers/src/files/dashboard_files/helpers/mod.rs b/api/libs/handlers/src/files/dashboard_files/helpers/mod.rs deleted file mode 100644 index 62dc9032c..000000000 --- a/api/libs/handlers/src/files/dashboard_files/helpers/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod get_dashboard_handler; - -pub use get_dashboard_handler::*; \ No newline at end of file diff --git a/api/libs/handlers/src/files/dashboard_files/mod.rs b/api/libs/handlers/src/files/dashboard_files/mod.rs deleted file mode 100644 index d288280e1..000000000 --- a/api/libs/handlers/src/files/dashboard_files/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod types; -mod helpers; - -pub use types::*; -pub use helpers::*; \ No newline at end of file diff --git a/api/libs/handlers/src/files/mod.rs b/api/libs/handlers/src/files/mod.rs deleted file mode 100644 index eda538aa4..000000000 --- a/api/libs/handlers/src/files/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod dashboard_files; - -pub use dashboard_files::*; diff --git a/api/libs/handlers/src/lib.rs b/api/libs/handlers/src/lib.rs index 08f66bd27..890908459 100644 --- a/api/libs/handlers/src/lib.rs +++ b/api/libs/handlers/src/lib.rs @@ -1,7 +1,7 @@ pub mod chats; pub mod collections; +pub mod dashboards; pub mod favorites; -pub mod files; pub mod logs; pub mod messages; pub mod metrics; diff --git a/api/src/routes/rest/routes/dashboards/get_dashboard.rs b/api/src/routes/rest/routes/dashboards/get_dashboard.rs index 4cca456bb..95dfc5bad 100644 --- a/api/src/routes/rest/routes/dashboards/get_dashboard.rs +++ b/api/src/routes/rest/routes/dashboards/get_dashboard.rs @@ -2,10 +2,9 @@ use crate::routes::rest::ApiResponse; use axum::extract::Path; use axum::http::StatusCode; use axum::Extension; -use handlers::files::dashboard_files::get_dashboard_handler::get_dashboard_handler; -use handlers::files::dashboard_files::BusterDashboardResponse; -use uuid::Uuid; +use handlers::dashboards::{get_dashboard_handler, BusterDashboardResponse}; use middleware::AuthenticatedUser; +use uuid::Uuid; pub async fn get_dashboard_rest_handler( Extension(user): Extension, diff --git a/api/src/routes/rest/routes/dashboards/list_dashboards.rs b/api/src/routes/rest/routes/dashboards/list_dashboards.rs new file mode 100644 index 000000000..412e2484b --- /dev/null +++ b/api/src/routes/rest/routes/dashboards/list_dashboards.rs @@ -0,0 +1,37 @@ +use crate::routes::rest::ApiResponse; +use axum::extract::Query; +use axum::http::StatusCode; +use axum::Extension; +use handlers::dashboards::{list_dashboard_handler, DashboardsListRequest, BusterDashboardListItem}; +use middleware::AuthenticatedUser; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct ListDashboardsQuery { + page_token: Option, + page_size: Option, + shared_with_me: Option, + only_my_dashboards: Option, +} + +pub async fn list_dashboard_rest_handler( + Extension(user): Extension, + Query(query): Query, +) -> Result>, (StatusCode, &'static str)> { + let request = DashboardsListRequest { + page_token: query.page_token.unwrap_or(0), + page_size: query.page_size.unwrap_or(25), + shared_with_me: query.shared_with_me, + only_my_dashboards: query.only_my_dashboards, + }; + + let dashboards = match list_dashboard_handler(&user.id, request).await { + Ok(dashboards) => dashboards, + Err(e) => { + tracing::error!("Error listing dashboards: {}", e); + return Err((StatusCode::INTERNAL_SERVER_ERROR, "Failed to list dashboards")); + } + }; + + Ok(ApiResponse::JsonData(dashboards)) +} diff --git a/api/src/routes/rest/routes/dashboards/mod.rs b/api/src/routes/rest/routes/dashboards/mod.rs index 7833b1764..feeffa2f5 100644 --- a/api/src/routes/rest/routes/dashboards/mod.rs +++ b/api/src/routes/rest/routes/dashboards/mod.rs @@ -5,8 +5,10 @@ use axum::{ // Placeholder modules that you'll need to create mod get_dashboard; +mod list_dashboards; pub fn router() -> Router { Router::new() .route("/:id", get(get_dashboard::get_dashboard_rest_handler)) + .route("/", get(list_dashboards::list_dashboard_rest_handler)) }