Skip to main content

slack_messaging/blocks/data_table/
cell.rs

1use crate::blocks::RichText;
2use crate::blocks::table::RawText;
3use serde::Serialize;
4use serde_json::Number;
5
6/// A table cell for DataTable block.
7#[derive(Debug, Clone, Serialize, PartialEq)]
8#[serde(untagged)]
9pub enum DataTableCell {
10    /// A plain text table cell
11    RawText(RawText),
12
13    /// A raw number table cell
14    RawNumber(RawNumber),
15
16    /// A rich text table cell
17    RichText(RichText),
18}
19
20impl<T: Into<String>> From<T> for DataTableCell {
21    fn from(value: T) -> Self {
22        Self::RawText(RawText::from(value))
23    }
24}
25
26impl From<RawText> for DataTableCell {
27    fn from(value: RawText) -> Self {
28        Self::RawText(value)
29    }
30}
31
32impl From<RawNumber> for DataTableCell {
33    fn from(value: RawNumber) -> Self {
34        Self::RawNumber(value)
35    }
36}
37
38impl From<RichText> for DataTableCell {
39    fn from(value: RichText) -> Self {
40        Self::RichText(value)
41    }
42}
43
44/// A raw number table cell value which can be used in [DataTable](crate::blocks::DataTable) block.
45#[derive(Debug, Clone, PartialEq)]
46pub struct RawNumber(Number, String);
47
48impl RawNumber {
49    pub fn new<N: Into<Number>, S: Into<String>>(value: N, text: S) -> Self {
50        Self(value.into(), text.into())
51    }
52}
53
54impl<N: Into<Number>, S: Into<String>> From<(N, S)> for RawNumber {
55    fn from((value, text): (N, S)) -> Self {
56        Self::new(value, text)
57    }
58}
59
60impl Serialize for RawNumber {
61    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
62    where
63        S: serde::Serializer
64    {
65        use serde::ser::SerializeStruct;
66
67        let mut state = serializer.serialize_struct("RawNumber", 3)?;
68        state.serialize_field("type", "raw_number")?;
69        state.serialize_field("value", &self.0)?;
70        state.serialize_field("text", &self.1)?;
71        state.end()
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use crate::blocks::rich_text::{RichTextSection, types::RichTextElementLink};
79
80    #[test]
81    fn it_serializes_into_raw_text_cell() {
82        let cell = DataTableCell::RawText("Data 1A".into());
83
84        let expected = serde_json::json!({
85            "type": "raw_text",
86            "text": "Data 1A",
87        });
88
89        let json = serde_json::to_value(cell).unwrap();
90        assert_eq!(json, expected);
91    }
92
93    #[test]
94    fn it_serializes_into_raw_number_cell() {
95        let cell = DataTableCell::RawNumber((10usize, "Data 1A").into());
96
97        let expected = serde_json::json!({
98            "type": "raw_number",
99            "value": 10,
100            "text": "Data 1A"
101        });
102
103        let json = serde_json::to_value(cell).unwrap();
104        assert_eq!(json, expected);
105    }
106
107    #[test]
108    fn it_serializes_into_rich_text_cell() {
109        let cell = DataTableCell::RichText(rich_text());
110
111        let expected = serde_json::json!({
112            "type": "rich_text",
113            "elements": [
114                {
115                    "type": "rich_text_section",
116                    "elements": [
117                        {
118                            "text": "Data 1B",
119                            "type": "link",
120                            "url": "https://slack.com"
121                        }
122                    ]
123                }
124            ]
125        });
126
127        let json = serde_json::to_value(cell).unwrap();
128        assert_eq!(json, expected);
129    }
130
131    fn rich_text() -> RichText {
132        RichText::builder()
133            .element(
134                RichTextSection::builder()
135                    .element(
136                        RichTextElementLink::builder()
137                            .text("Data 1B")
138                            .url("https://slack.com")
139                            .build()
140                            .unwrap(),
141                    )
142                    .build()
143                    .unwrap(),
144            )
145            .build()
146            .unwrap()
147    }
148}