#[derive(Debug, Clone)]
pub struct DashboardConfig {
pub admin_token: Option<String>,
pub path: String,
pub title: String,
pub replay_api_path: String,
}
impl Default for DashboardConfig {
fn default() -> Self {
Self::new()
}
}
impl DashboardConfig {
pub fn new() -> Self {
Self {
admin_token: None,
path: "/__rustapi/dashboard".to_string(),
title: "RustAPI System Dashboard".to_string(),
replay_api_path: "/__rustapi/replays".to_string(),
}
}
pub fn admin_token(mut self, token: impl Into<String>) -> Self {
self.admin_token = Some(token.into());
self
}
pub fn path(mut self, path: impl Into<String>) -> Self {
self.path = normalize_path_prefix(path.into());
self
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = title.into();
self
}
pub fn replay_api_path(mut self, path: impl Into<String>) -> Self {
self.replay_api_path = normalize_path_prefix(path.into());
self
}
pub(crate) fn normalize_paths(&mut self) {
self.path = normalize_path_prefix(std::mem::take(&mut self.path));
self.replay_api_path = normalize_path_prefix(std::mem::take(&mut self.replay_api_path));
}
pub(crate) fn normalized_path(&self) -> String {
normalize_path_prefix(self.path.clone())
}
}
fn normalize_path_prefix(path: String) -> String {
let trimmed = path.trim();
if trimmed.is_empty() {
return "/".to_string();
}
let mut normalized = if trimmed.starts_with('/') {
trimmed.to_string()
} else {
format!("/{trimmed}")
};
while normalized.len() > 1 && normalized.ends_with('/') {
normalized.pop();
}
normalized
}