Skip to main content

systemprompt_models/artifacts/dashboard/section_data/
metrics.rs

1//! Metric-card section payloads.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
10pub struct MetricsCardsData {
11    pub cards: Vec<MetricCard>,
12}
13
14impl MetricsCardsData {
15    pub const fn new(cards: Vec<MetricCard>) -> Self {
16        Self { cards }
17    }
18
19    pub fn add_card(mut self, card: MetricCard) -> Self {
20        self.cards.push(card);
21        self
22    }
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
26pub struct MetricCard {
27    pub title: String,
28    pub value: String,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub subtitle: Option<String>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub icon: Option<String>,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub status: Option<MetricStatus>,
35}
36
37#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, Default)]
38#[serde(rename_all = "lowercase")]
39pub enum MetricStatus {
40    Success,
41    Warning,
42    Error,
43    #[default]
44    Info,
45}
46
47impl std::str::FromStr for MetricStatus {
48    type Err = String;
49
50    fn from_str(s: &str) -> Result<Self, Self::Err> {
51        match s.to_lowercase().as_str() {
52            "success" | "healthy" | "ok" | "active" => Ok(Self::Success),
53            "warning" | "degraded" => Ok(Self::Warning),
54            "error" | "failed" | "critical" => Ok(Self::Error),
55            "info" | "unknown" => Ok(Self::Info),
56            _ => Err(format!("Invalid metric status: {s}")),
57        }
58    }
59}
60
61impl MetricCard {
62    pub fn new(title: impl Into<String>, value: impl Into<String>) -> Self {
63        Self {
64            title: title.into(),
65            value: value.into(),
66            subtitle: None,
67            icon: None,
68            status: None,
69        }
70    }
71
72    pub fn with_subtitle(mut self, subtitle: impl Into<String>) -> Self {
73        self.subtitle = Some(subtitle.into());
74        self
75    }
76
77    pub fn with_icon(mut self, icon: impl Into<String>) -> Self {
78        self.icon = Some(icon.into());
79        self
80    }
81
82    pub const fn with_status(mut self, status: MetricStatus) -> Self {
83        self.status = Some(status);
84        self
85    }
86}