mirror of https://github.com/buster-so/buster.git
BUS-1454: Add multiple color themes and refactor organization color palette retrieval logic
This commit is contained in:
parent
d5beb5edeb
commit
227168bb62
|
@ -1,5 +1,6 @@
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use database::pool::get_pg_pool;
|
use database::pool::get_pg_pool;
|
||||||
|
use database::schema::organizations;
|
||||||
use diesel::{ExpressionMethods, QueryDsl};
|
use diesel::{ExpressionMethods, QueryDsl};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -11,40 +12,226 @@ pub const DEFAULT_COLOR_PALETTE: [&str; 10] = [
|
||||||
"#31FCB4", "#E83562"
|
"#31FCB4", "#E83562"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Define all default palettes to match TypeScript
|
||||||
|
const SOFT_THEME: [&str; 10] = [
|
||||||
|
"#36A2EB", "#4BC0C0", "#9966FF", "#FF9F40", "#C9CBCF",
|
||||||
|
"#66FF66", "#FF66B2", "#66B2FF", "#FF6384", "#5C6BC0"
|
||||||
|
];
|
||||||
|
|
||||||
|
const RAINBOW_THEME: [&str; 10] = [
|
||||||
|
"#ff595e", "#ff924c", "#ffca3a", "#c5ca30", "#8ac926",
|
||||||
|
"#36949d", "#1982c4", "#4267ac", "#565aa0", "#6a4c93"
|
||||||
|
];
|
||||||
|
|
||||||
|
const BOLD_RAINBOW_THEME: [&str; 9] = [
|
||||||
|
"#ffcd00", "#faff98", "#bbdd00", "#5a8900", "#009c89",
|
||||||
|
"#e31d04", "#ff7b83", "#ffa6a0", "#320e00"
|
||||||
|
];
|
||||||
|
|
||||||
|
const VIBRANT_RAINBOW_THEME: [&str; 9] = [
|
||||||
|
"#9b5de5", "#c65ccd", "#f15bb5", "#f8a07b", "#fee440",
|
||||||
|
"#7fd09d", "#00bbf9", "#00d8e7", "#00f5d4"
|
||||||
|
];
|
||||||
|
|
||||||
|
const CORPORATE_THEME: [&str; 10] = [
|
||||||
|
"#73b7b8", "#52a1a3", "#76c8b1", "#50b99b", "#dc244b",
|
||||||
|
"#af1d3c", "#f6cb52", "#f3b816", "#f05a29", "#d23f0f"
|
||||||
|
];
|
||||||
|
|
||||||
|
const EMERALD_SPECTRUM_THEME: [&str; 10] = [
|
||||||
|
"#75F0A0", "#6FD5EC", "#6B69E8", "#D064E3", "#DD5F87",
|
||||||
|
"#D7995B", "#A8D157", "#53CA67", "#50C3C3", "#4E60BC"
|
||||||
|
];
|
||||||
|
|
||||||
|
const VIBRANT_JEWEL_TONES_THEME: [&str; 10] = [
|
||||||
|
"#F07589", "#EB6FEB", "#7F6BE6", "#67B7E0", "#63D99E",
|
||||||
|
"#86D260", "#CBB85D", "#C25B5B", "#BA5AA8", "#7759B1"
|
||||||
|
];
|
||||||
|
|
||||||
|
const RED_YELLOW_BLUE_THEME: [&str; 10] = [
|
||||||
|
"#f94144", "#f3722c", "#f8961e", "#f9844a", "#f9c74f",
|
||||||
|
"#90be6d", "#43aa8b", "#4d908e", "#577590", "#277da1"
|
||||||
|
];
|
||||||
|
|
||||||
|
const PASTEL_RAINBOW_THEME: [&str; 9] = [
|
||||||
|
"#ffadad", "#ffd6a5", "#fdffb6", "#caffbf", "#9bf6ff",
|
||||||
|
"#a0c4ff", "#bdb2ff", "#ffc6ff", "#ffd1ff"
|
||||||
|
];
|
||||||
|
|
||||||
|
const DIVERSE_DARK_PALETTE_GREEN_THEME: [&str; 10] = [
|
||||||
|
"#669900", "#99cc33", "#ccee66", "#006699", "#3399cc",
|
||||||
|
"#990066", "#cc3399", "#ff6600", "#ff9900", "#ffcc00"
|
||||||
|
];
|
||||||
|
|
||||||
|
const DIVERSE_DARK_PALETTE_BLACK_THEME: [&str; 9] = [
|
||||||
|
"#303638", "#f0c808", "#5d4b20", "#469374", "#9341b3",
|
||||||
|
"#e3427d", "#e68653", "#ebe0b0", "#edfbba"
|
||||||
|
];
|
||||||
|
|
||||||
|
const VIBRANT_PASTEL_THEME: [&str; 10] = [
|
||||||
|
"#F07575", "#ECD76F", "#93E869", "#64E3A3", "#5FB3DD",
|
||||||
|
"#705BD7", "#D157D1", "#CA5367", "#C39B50", "#86BC4E"
|
||||||
|
];
|
||||||
|
|
||||||
|
const BLUE_TO_ORANGE_GRADIENT: [&str; 10] = [
|
||||||
|
"#8ecae6", "#73bfdc", "#58b4d1", "#219ebc", "#126782",
|
||||||
|
"#023047", "#ffb703", "#fd9e02", "#fb8500", "#fb9017"
|
||||||
|
];
|
||||||
|
|
||||||
|
const VIBRANT_RAINBOW: [&str; 10] = [
|
||||||
|
"#F0DC75", "#98EC6F", "#69E8A8", "#64B8E3", "#745FDD",
|
||||||
|
"#D75BD7", "#D1576B", "#CAA153", "#8CC350", "#4EBC70"
|
||||||
|
];
|
||||||
|
|
||||||
|
const FOREST_LAKE_GRADIENT: [&str; 10] = [
|
||||||
|
"#40916c", "#52b788", "#74c69d", "#95d5b2", "#b7e4c7",
|
||||||
|
"#89c2d9", "#61a5c2", "#468faf", "#2a6f97", "#013a63"
|
||||||
|
];
|
||||||
|
|
||||||
|
const GREENS_THEME: [&str; 10] = [
|
||||||
|
"#99e2b4", "#88d4ab", "#78c6a3", "#67b99a", "#56ab91",
|
||||||
|
"#469d89", "#358f80", "#248277", "#14746f", "#036666"
|
||||||
|
];
|
||||||
|
|
||||||
|
const MORE_BLUES_DARK_TO_LIGHT_THEME: [&str; 10] = [
|
||||||
|
"#03045e", "#023e8a", "#0077b6", "#0096c7", "#00b4d8",
|
||||||
|
"#48cae4", "#90e0ef", "#ade8f4", "#caf0f8", "#d5f3f9"
|
||||||
|
];
|
||||||
|
|
||||||
|
const PURPLE_THEME: [&str; 10] = [
|
||||||
|
"#4a148c", "#6a1b9a", "#7b1fa2", "#8e24aa", "#9c27b0",
|
||||||
|
"#ab47bc", "#ba68c8", "#ce93d8", "#e1bee7", "#f3e5f5"
|
||||||
|
];
|
||||||
|
|
||||||
|
const ORANGE_THEME: [&str; 10] = [
|
||||||
|
"#e65100", "#ef6c00", "#f57c00", "#fb8c00", "#ff9800",
|
||||||
|
"#ffa726", "#ffb74d", "#ffcc80", "#ffe0b2", "#fff3e0"
|
||||||
|
];
|
||||||
|
|
||||||
|
const RED_THEME: [&str; 10] = [
|
||||||
|
"#b71c1c", "#c62828", "#d32f2f", "#e53935", "#f44336",
|
||||||
|
"#ef5350", "#e57373", "#e35555", "#d13030", "#b71c1c"
|
||||||
|
];
|
||||||
|
|
||||||
|
const TEAL_THEME: [&str; 10] = [
|
||||||
|
"#004d4d", "#006666", "#008080", "#009999", "#00b3b3",
|
||||||
|
"#00cccc", "#00b3b3", "#009999", "#008080", "#006666"
|
||||||
|
];
|
||||||
|
|
||||||
|
const BLUE_THEME: [&str; 10] = [
|
||||||
|
"#0d47a1", "#1565c0", "#1976d2", "#1e88e5", "#2196f3",
|
||||||
|
"#42a5f5", "#2196f3", "#1976d2", "#1565c0", "#0d47a1"
|
||||||
|
];
|
||||||
|
|
||||||
|
const BROWN_THEME: [&str; 10] = [
|
||||||
|
"#3e2723", "#4e342e", "#5d4037", "#6d4c41", "#795548",
|
||||||
|
"#8d6e63", "#795548", "#6d4c41", "#5d4037", "#4e342e"
|
||||||
|
];
|
||||||
|
|
||||||
|
const PINK_THEME: [&str; 10] = [
|
||||||
|
"#880e4f", "#ad1457", "#c2185b", "#d81b60", "#e91e63",
|
||||||
|
"#ec407a", "#e91e63", "#d81b60", "#c2185b", "#ad1457"
|
||||||
|
];
|
||||||
|
|
||||||
|
// Map default palette IDs to their color arrays
|
||||||
|
fn get_default_palette_by_id(palette_id: &str) -> Option<Vec<String>> {
|
||||||
|
// Remove the __DEFAULT__ prefix and parse the palette name
|
||||||
|
if !palette_id.starts_with("__DEFAULT__") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let palette_suffix = &palette_id[11..]; // Skip "__DEFAULT__"
|
||||||
|
|
||||||
|
match palette_suffix {
|
||||||
|
"buster-0" => Some(DEFAULT_COLOR_PALETTE.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"rainbow-1" => Some(RAINBOW_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"soft-2" => Some(SOFT_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"red-yellow-blue-3" => Some(RED_YELLOW_BLUE_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"pastel-rainbow-4" => Some(PASTEL_RAINBOW_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"bold-rainbow-5" => Some(BOLD_RAINBOW_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"modern-6" => Some(VIBRANT_RAINBOW_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"corporate-7" => Some(CORPORATE_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"jewel-tones-8" => Some(VIBRANT_JEWEL_TONES_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"soft-pastel-9" => Some(VIBRANT_PASTEL_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"diverse-dark-10" => Some(DIVERSE_DARK_PALETTE_BLACK_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"emerald-spectrum-11" => Some(EMERALD_SPECTRUM_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"deep-forest-12" => Some(DIVERSE_DARK_PALETTE_GREEN_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"vibrant-rainbow-13" => Some(VIBRANT_RAINBOW.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
// Monochrome themes
|
||||||
|
"greens-0" => Some(GREENS_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"blue---orange-1" => Some(BLUE_TO_ORANGE_GRADIENT.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"forest-sunset-2" => Some(FOREST_LAKE_GRADIENT.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"more-blues-3" => Some(MORE_BLUES_DARK_TO_LIGHT_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"purple-4" => Some(PURPLE_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"orange-5" => Some(ORANGE_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"red-6" => Some(RED_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"teal-7" => Some(TEAL_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"brown-8" => Some(BROWN_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"pink-9" => Some(PINK_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
"blue-10" => Some(BLUE_THEME.iter().map(|&s| s.to_string()).collect()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_organization_color_palette(organization_id: &Uuid) -> Result<Option<Vec<String>>> {
|
pub async fn get_organization_color_palette(organization_id: &Uuid) -> Result<Option<Vec<String>>> {
|
||||||
let mut conn = get_pg_pool().get().await?;
|
let mut conn = get_pg_pool().get().await?;
|
||||||
|
|
||||||
let config_result = diesel::sql_query(
|
// Query the organizations table directly using Diesel query builder
|
||||||
"SELECT config FROM users
|
let org_result = organizations::table
|
||||||
INNER JOIN users_to_organizations ON users.id = users_to_organizations.user_id
|
.select(organizations::organization_color_palettes)
|
||||||
WHERE users_to_organizations.organization_id = $1
|
.filter(organizations::id.eq(organization_id))
|
||||||
AND users_to_organizations.deleted_at IS NULL
|
.filter(organizations::deleted_at.is_null())
|
||||||
LIMIT 1"
|
.first::<Value>(&mut conn)
|
||||||
)
|
.await;
|
||||||
.bind::<diesel::sql_types::Uuid, _>(organization_id)
|
|
||||||
.get_result::<ConfigResult>(&mut conn)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match config_result {
|
match org_result {
|
||||||
Ok(config_row) => {
|
Ok(color_palettes_value) => {
|
||||||
if let Some(config_value) = config_row.config {
|
// Check if there's a selectedId field
|
||||||
if let Some(selected_palette) = config_value.get("selectedDictionaryPalette") {
|
if let Some(selected_id) = color_palettes_value.get("selectedId") {
|
||||||
if let Some(colors) = selected_palette.get("colors") {
|
if let Some(selected_id_str) = selected_id.as_str() {
|
||||||
if let Some(colors_array) = colors.as_array() {
|
// Check if it's a default palette ID
|
||||||
let palette: Vec<String> = colors_array
|
if selected_id_str.starts_with("__DEFAULT__") {
|
||||||
.iter()
|
// Return the corresponding default palette
|
||||||
.filter_map(|c| c.as_str().map(|s| s.to_string()))
|
if let Some(default_palette) = get_default_palette_by_id(selected_id_str) {
|
||||||
.collect();
|
return Ok(Some(default_palette));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// It's a custom palette ID, look for it in the palettes array
|
||||||
|
if let Some(palettes) = color_palettes_value.get("palettes") {
|
||||||
|
if let Some(palettes_array) = palettes.as_array() {
|
||||||
|
// Find the palette with matching ID
|
||||||
|
for palette in palettes_array {
|
||||||
|
if let Some(id) = palette.get("id") {
|
||||||
|
if let Some(id_str) = id.as_str() {
|
||||||
|
if id_str == selected_id_str {
|
||||||
|
// Found the selected palette
|
||||||
|
if let Some(colors) = 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() {
|
if !palette.is_empty() {
|
||||||
return Ok(Some(palette));
|
return Ok(Some(palette));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(last_used) = config_value.get("last_used_color_palette") {
|
// Legacy fallbacks for older data structures
|
||||||
if let Some(colors_array) = last_used.as_array() {
|
// Check for selectedDictionaryPalette
|
||||||
|
if let Some(selected_palette) = color_palettes_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
|
let palette: Vec<String> = colors_array
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|c| c.as_str().map(|s| s.to_string()))
|
.filter_map(|c| c.as_str().map(|s| s.to_string()))
|
||||||
|
@ -57,9 +244,24 @@ pub async fn get_organization_color_palette(organization_id: &Uuid) -> Result<Op
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fall back to last_used_color_palette if nothing else is available
|
||||||
|
if let Some(last_used) = color_palettes_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)
|
Ok(None)
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
// Organization not found or no color palettes set
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue