use serde::{Deserialize, Serialize};
use super::tag::{tagged_enum, Tag, Tagged};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DataVisualizationBlock {
r#type: Tag<Self>,
pub title: String,
pub chart: Chart,
#[serde(skip_serializing_if = "Option::is_none")]
pub block_id: Option<String>,
}
impl Tagged for DataVisualizationBlock {
const TAG: &'static str = "data_visualization";
}
impl DataVisualizationBlock {
pub fn new(title: impl Into<String>, chart: impl Into<Chart>) -> Self {
Self {
r#type: Tag::default(),
title: title.into(),
chart: chart.into(),
block_id: None,
}
}
pub fn block_id(mut self, block_id: impl Into<String>) -> Self {
self.block_id = Some(block_id.into());
self
}
}
tagged_enum! {
pub enum Chart("type") {
Pie(PieChart),
Bar(BarChart),
Area(AreaChart),
Line(LineChart),
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PieChart {
r#type: Tag<Self>,
pub segments: Vec<Segment>,
}
impl Tagged for PieChart {
const TAG: &'static str = "pie";
}
impl PieChart {
pub fn new(segments: Vec<Segment>) -> Self {
Self {
r#type: Tag::default(),
segments,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BarChart {
r#type: Tag<Self>,
pub series: Vec<DataSeries>,
pub axis_config: AxisConfig,
}
impl Tagged for BarChart {
const TAG: &'static str = "bar";
}
impl BarChart {
pub fn new(series: Vec<DataSeries>, axis_config: AxisConfig) -> Self {
Self {
r#type: Tag::default(),
series,
axis_config,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AreaChart {
r#type: Tag<Self>,
pub series: Vec<DataSeries>,
pub axis_config: AxisConfig,
}
impl Tagged for AreaChart {
const TAG: &'static str = "area";
}
impl AreaChart {
pub fn new(series: Vec<DataSeries>, axis_config: AxisConfig) -> Self {
Self {
r#type: Tag::default(),
series,
axis_config,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LineChart {
r#type: Tag<Self>,
pub series: Vec<DataSeries>,
pub axis_config: AxisConfig,
}
impl Tagged for LineChart {
const TAG: &'static str = "line";
}
impl LineChart {
pub fn new(series: Vec<DataSeries>, axis_config: AxisConfig) -> Self {
Self {
r#type: Tag::default(),
series,
axis_config,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Segment {
pub label: String,
pub value: f64,
}
impl Segment {
pub fn new(label: impl Into<String>, value: f64) -> Self {
Self {
label: label.into(),
value,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DataSeries {
pub name: String,
pub data: Vec<DataPoint>,
}
impl DataSeries {
pub fn new(name: impl Into<String>, data: Vec<DataPoint>) -> Self {
Self {
name: name.into(),
data,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DataPoint {
pub label: String,
pub value: f64,
}
impl DataPoint {
pub fn new(label: impl Into<String>, value: f64) -> Self {
Self {
label: label.into(),
value,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AxisConfig {
pub categories: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub x_label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub y_label: Option<String>,
}
impl AxisConfig {
pub fn new(categories: Vec<String>) -> Self {
Self {
categories,
x_label: None,
y_label: None,
}
}
pub fn x_label(mut self, x_label: impl Into<String>) -> Self {
self.x_label = Some(x_label.into());
self
}
pub fn y_label(mut self, y_label: impl Into<String>) -> Self {
self.y_label = Some(y_label.into());
self
}
}