mirror of https://github.com/buster-so/buster.git
BUS-1453: Implement color fallback logic for metric handlers
Co-Authored-By: Dallin Bentley <dallinbentley98@gmail.com>
This commit is contained in:
parent
2de702f425
commit
d5beb5edeb
|
@ -0,0 +1,125 @@
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use database::pool::get_pg_pool;
|
||||||
|
use diesel::{ExpressionMethods, QueryDsl};
|
||||||
|
use diesel_async::RunQueryDsl;
|
||||||
|
use serde_json::Value;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub const DEFAULT_COLOR_PALETTE: [&str; 10] = [
|
||||||
|
"#B399FD", "#FC8497", "#FBBC30", "#279EFF",
|
||||||
|
"#E83562", "#41F8FF", "#F3864F", "#C82184",
|
||||||
|
"#31FCB4", "#E83562"
|
||||||
|
];
|
||||||
|
|
||||||
|
pub async fn get_organization_color_palette(organization_id: &Uuid) -> Result<Option<Vec<String>>> {
|
||||||
|
let mut conn = get_pg_pool().get().await?;
|
||||||
|
|
||||||
|
let config_result = diesel::sql_query(
|
||||||
|
"SELECT config FROM users
|
||||||
|
INNER JOIN users_to_organizations ON users.id = users_to_organizations.user_id
|
||||||
|
WHERE users_to_organizations.organization_id = $1
|
||||||
|
AND users_to_organizations.deleted_at IS NULL
|
||||||
|
LIMIT 1"
|
||||||
|
)
|
||||||
|
.bind::<diesel::sql_types::Uuid, _>(organization_id)
|
||||||
|
.get_result::<ConfigResult>(&mut conn)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match config_result {
|
||||||
|
Ok(config_row) => {
|
||||||
|
if let Some(config_value) = config_row.config {
|
||||||
|
if let Some(selected_palette) = config_value.get("selectedDictionaryPalette") {
|
||||||
|
if let Some(colors) = selected_palette.get("colors") {
|
||||||
|
if let Some(colors_array) = colors.as_array() {
|
||||||
|
let palette: Vec<String> = colors_array
|
||||||
|
.iter()
|
||||||
|
.filter_map(|c| c.as_str().map(|s| s.to_string()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if !palette.is_empty() {
|
||||||
|
return Ok(Some(palette));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(last_used) = config_value.get("last_used_color_palette") {
|
||||||
|
if let Some(colors_array) = last_used.as_array() {
|
||||||
|
let palette: Vec<String> = colors_array
|
||||||
|
.iter()
|
||||||
|
.filter_map(|c| c.as_str().map(|s| s.to_string()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if !palette.is_empty() {
|
||||||
|
return Ok(Some(palette));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_default_color_palette() -> Vec<String> {
|
||||||
|
DEFAULT_COLOR_PALETTE.iter().map(|&s| s.to_string()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn apply_color_fallback(
|
||||||
|
chart_config: &mut database::types::ChartConfig,
|
||||||
|
organization_id: &Uuid,
|
||||||
|
) -> Result<()> {
|
||||||
|
let colors_already_set = match chart_config {
|
||||||
|
database::types::ChartConfig::Bar(config) => config.base.colors.is_some(),
|
||||||
|
database::types::ChartConfig::Line(config) => config.base.colors.is_some(),
|
||||||
|
database::types::ChartConfig::Scatter(config) => config.base.colors.is_some(),
|
||||||
|
database::types::ChartConfig::Pie(config) => config.base.colors.is_some(),
|
||||||
|
database::types::ChartConfig::Combo(config) => config.base.colors.is_some(),
|
||||||
|
database::types::ChartConfig::Metric(_) => true, // Metric doesn't use colors
|
||||||
|
database::types::ChartConfig::Table(_) => true, // Table doesn't use colors
|
||||||
|
};
|
||||||
|
|
||||||
|
if colors_already_set {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let org_palette = get_organization_color_palette(organization_id).await?;
|
||||||
|
|
||||||
|
let palette = if let Some(palette) = org_palette {
|
||||||
|
palette
|
||||||
|
} else {
|
||||||
|
get_default_color_palette()
|
||||||
|
};
|
||||||
|
|
||||||
|
match chart_config {
|
||||||
|
database::types::ChartConfig::Bar(config) => {
|
||||||
|
config.base.colors = Some(palette);
|
||||||
|
},
|
||||||
|
database::types::ChartConfig::Line(config) => {
|
||||||
|
config.base.colors = Some(palette);
|
||||||
|
},
|
||||||
|
database::types::ChartConfig::Scatter(config) => {
|
||||||
|
config.base.colors = Some(palette);
|
||||||
|
},
|
||||||
|
database::types::ChartConfig::Pie(config) => {
|
||||||
|
config.base.colors = Some(palette);
|
||||||
|
},
|
||||||
|
database::types::ChartConfig::Combo(config) => {
|
||||||
|
config.base.colors = Some(palette);
|
||||||
|
},
|
||||||
|
database::types::ChartConfig::Metric(_) => {}, // No colors to set
|
||||||
|
database::types::ChartConfig::Table(_) => {}, // No colors to set
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(diesel::QueryableByName, Debug)]
|
||||||
|
struct ConfigResult {
|
||||||
|
#[diesel(sql_type = diesel::sql_types::Jsonb)]
|
||||||
|
config: Option<Value>,
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ use serde_yaml;
|
||||||
use sharing::asset_access_checks::check_metric_collection_access;
|
use sharing::asset_access_checks::check_metric_collection_access;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::metrics::color_palette_helpers::apply_color_fallback;
|
||||||
use crate::metrics::types::{AssociatedCollection, AssociatedDashboard, BusterMetric, BusterShareIndividual, Dataset};
|
use crate::metrics::types::{AssociatedCollection, AssociatedDashboard, BusterMetric, BusterShareIndividual, Dataset};
|
||||||
use crate::utils::workspace::count_workspace_members;
|
use crate::utils::workspace::count_workspace_members;
|
||||||
use database::enums::{AssetPermissionRole, AssetType, IdentityType};
|
use database::enums::{AssetPermissionRole, AssetType, IdentityType};
|
||||||
|
@ -448,6 +449,11 @@ pub async fn get_metric_for_dashboard_handler(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut final_chart_config = resolved_chart_config.clone();
|
||||||
|
if let Err(e) = apply_color_fallback(&mut final_chart_config, &metric_file.organization_id).await {
|
||||||
|
tracing::warn!(metric_id = %metric_id, error = %e, "Failed to apply color fallback logic, continuing with original chart config");
|
||||||
|
}
|
||||||
|
|
||||||
// Get workspace sharing enabled by email if set
|
// Get workspace sharing enabled by email if set
|
||||||
let workspace_sharing_enabled_by = if let Some(enabled_by_id) = metric_file.workspace_sharing_enabled_by {
|
let workspace_sharing_enabled_by = if let Some(enabled_by_id) = metric_file.workspace_sharing_enabled_by {
|
||||||
users::table
|
users::table
|
||||||
|
@ -488,7 +494,7 @@ pub async fn get_metric_for_dashboard_handler(
|
||||||
datasets,
|
datasets,
|
||||||
data_source_id: metric_file.data_source_id,
|
data_source_id: metric_file.data_source_id,
|
||||||
error: None,
|
error: None,
|
||||||
chart_config: Some(resolved_chart_config),
|
chart_config: Some(final_chart_config), // Use chart config with color fallback applied
|
||||||
data_metadata,
|
data_metadata,
|
||||||
status: metric_file.verification,
|
status: metric_file.verification,
|
||||||
evaluation_score,
|
evaluation_score,
|
||||||
|
|
|
@ -7,6 +7,7 @@ use serde_yaml;
|
||||||
use sharing::asset_access_checks::check_metric_collection_access;
|
use sharing::asset_access_checks::check_metric_collection_access;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::metrics::color_palette_helpers::apply_color_fallback;
|
||||||
use crate::metrics::types::{AssociatedCollection, AssociatedDashboard, BusterMetric, Dataset};
|
use crate::metrics::types::{AssociatedCollection, AssociatedDashboard, BusterMetric, Dataset};
|
||||||
use crate::utils::workspace::count_workspace_members;
|
use crate::utils::workspace::count_workspace_members;
|
||||||
use database::enums::{AssetPermissionRole, AssetType, IdentityType};
|
use database::enums::{AssetPermissionRole, AssetType, IdentityType};
|
||||||
|
@ -304,6 +305,11 @@ pub async fn get_metric_handler(
|
||||||
tracing::debug!(metric_id = %metric_id, latest_version = resolved_version_num, "Determined latest version number");
|
tracing::debug!(metric_id = %metric_id, latest_version = resolved_version_num, "Determined latest version number");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut final_chart_config = resolved_chart_config.clone();
|
||||||
|
if let Err(e) = apply_color_fallback(&mut final_chart_config, &metric_file.organization_id).await {
|
||||||
|
tracing::warn!(metric_id = %metric_id, error = %e, "Failed to apply color fallback logic, continuing with original chart config");
|
||||||
|
}
|
||||||
|
|
||||||
// Convert the selected content to pretty YAML for the 'file' field
|
// Convert the selected content to pretty YAML for the 'file' field
|
||||||
let file = match serde_yaml::to_string(&resolved_content_for_yaml) {
|
let file = match serde_yaml::to_string(&resolved_content_for_yaml) {
|
||||||
Ok(yaml) => yaml,
|
Ok(yaml) => yaml,
|
||||||
|
@ -494,7 +500,7 @@ pub async fn get_metric_handler(
|
||||||
datasets, // Fetched based on resolved_dataset_ids (for display purposes only)
|
datasets, // Fetched based on resolved_dataset_ids (for display purposes only)
|
||||||
data_source_id: metric_file.data_source_id, // Use canonical ID (Uuid) from main record
|
data_source_id: metric_file.data_source_id, // Use canonical ID (Uuid) from main record
|
||||||
error: None, // Assume ok
|
error: None, // Assume ok
|
||||||
chart_config: Some(resolved_chart_config), // Use resolved chart config
|
chart_config: Some(final_chart_config), // Use chart config with color fallback applied
|
||||||
data_metadata, // Not versioned
|
data_metadata, // Not versioned
|
||||||
status: metric_file.verification, // Not versioned
|
status: metric_file.verification, // Not versioned
|
||||||
evaluation_score, // Not versioned
|
evaluation_score, // Not versioned
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod bulk_update_metrics_handler;
|
pub mod bulk_update_metrics_handler;
|
||||||
|
pub mod color_palette_helpers;
|
||||||
pub mod delete_metric_handler;
|
pub mod delete_metric_handler;
|
||||||
pub mod get_metric_data_handler;
|
pub mod get_metric_data_handler;
|
||||||
pub mod get_metric_handler;
|
pub mod get_metric_handler;
|
||||||
|
|
Loading…
Reference in New Issue