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