Skip to main content

slack_web_api/blocks/
chart.rs

1use serde::{Deserialize, Serialize};
2
3use super::tag::{tagged_enum, Tag, Tagged};
4
5/// A chart. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7pub struct DataVisualizationBlock {
8    r#type: Tag<Self>,
9    pub title: String,
10    pub chart: Chart,
11    #[serde(skip_serializing_if = "Option::is_none")]
12    pub block_id: Option<String>,
13}
14
15impl Tagged for DataVisualizationBlock {
16    const TAG: &'static str = "data_visualization";
17}
18
19impl DataVisualizationBlock {
20    pub fn new(title: impl Into<String>, chart: impl Into<Chart>) -> Self {
21        Self {
22            r#type: Tag::default(),
23            title: title.into(),
24            chart: chart.into(),
25            block_id: None,
26        }
27    }
28
29    pub fn block_id(mut self, block_id: impl Into<String>) -> Self {
30        self.block_id = Some(block_id.into());
31        self
32    }
33}
34
35tagged_enum! {
36    /// The chart payload for each chart type. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
37    pub enum Chart("type") {
38        Pie(PieChart),
39        Bar(BarChart),
40        Area(AreaChart),
41        Line(LineChart),
42    }
43}
44
45/// A pie chart. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47pub struct PieChart {
48    r#type: Tag<Self>,
49    pub segments: Vec<Segment>,
50}
51
52impl Tagged for PieChart {
53    const TAG: &'static str = "pie";
54}
55
56impl PieChart {
57    pub fn new(segments: Vec<Segment>) -> Self {
58        Self {
59            r#type: Tag::default(),
60            segments,
61        }
62    }
63}
64
65/// A bar chart. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67pub struct BarChart {
68    r#type: Tag<Self>,
69    pub series: Vec<DataSeries>,
70    pub axis_config: AxisConfig,
71}
72
73impl Tagged for BarChart {
74    const TAG: &'static str = "bar";
75}
76
77impl BarChart {
78    pub fn new(series: Vec<DataSeries>, axis_config: AxisConfig) -> Self {
79        Self {
80            r#type: Tag::default(),
81            series,
82            axis_config,
83        }
84    }
85}
86
87/// An area chart. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
88#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
89pub struct AreaChart {
90    r#type: Tag<Self>,
91    pub series: Vec<DataSeries>,
92    pub axis_config: AxisConfig,
93}
94
95impl Tagged for AreaChart {
96    const TAG: &'static str = "area";
97}
98
99impl AreaChart {
100    pub fn new(series: Vec<DataSeries>, axis_config: AxisConfig) -> Self {
101        Self {
102            r#type: Tag::default(),
103            series,
104            axis_config,
105        }
106    }
107}
108
109/// A line chart. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111pub struct LineChart {
112    r#type: Tag<Self>,
113    pub series: Vec<DataSeries>,
114    pub axis_config: AxisConfig,
115}
116
117impl Tagged for LineChart {
118    const TAG: &'static str = "line";
119}
120
121impl LineChart {
122    pub fn new(series: Vec<DataSeries>, axis_config: AxisConfig) -> Self {
123        Self {
124            r#type: Tag::default(),
125            series,
126            axis_config,
127        }
128    }
129}
130
131/// One slice of a pie chart. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
132#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
133pub struct Segment {
134    pub label: String,
135    pub value: f64,
136}
137
138impl Segment {
139    pub fn new(label: impl Into<String>, value: f64) -> Self {
140        Self {
141            label: label.into(),
142            value,
143        }
144    }
145}
146
147/// A data series in a chart. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
148#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
149pub struct DataSeries {
150    pub name: String,
151    pub data: Vec<DataPoint>,
152}
153
154impl DataSeries {
155    pub fn new(name: impl Into<String>, data: Vec<DataPoint>) -> Self {
156        Self {
157            name: name.into(),
158            data,
159        }
160    }
161}
162
163/// One data point in a series. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
164#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
165pub struct DataPoint {
166    pub label: String,
167    pub value: f64,
168}
169
170impl DataPoint {
171    pub fn new(label: impl Into<String>, value: f64) -> Self {
172        Self {
173            label: label.into(),
174            value,
175        }
176    }
177}
178
179/// X-axis categories and axis labels. <https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block>
180#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
181pub struct AxisConfig {
182    pub categories: Vec<String>,
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub x_label: Option<String>,
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub y_label: Option<String>,
187}
188
189impl AxisConfig {
190    pub fn new(categories: Vec<String>) -> Self {
191        Self {
192            categories,
193            x_label: None,
194            y_label: None,
195        }
196    }
197
198    pub fn x_label(mut self, x_label: impl Into<String>) -> Self {
199        self.x_label = Some(x_label.into());
200        self
201    }
202
203    pub fn y_label(mut self, y_label: impl Into<String>) -> Self {
204        self.y_label = Some(y_label.into());
205        self
206    }
207}