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