slack_messaging/blocks/elements/
types.rs

1use crate::composition_objects::{Plain, Text};
2use crate::validators::*;
3
4use serde::Serialize;
5use slack_messaging_derive::Builder;
6
7/// Icons for [`IconButton`](crate::blocks::elements::IconButton).
8#[derive(Debug, Copy, Clone, Serialize, PartialEq)]
9#[serde(rename_all = "snake_case")]
10pub enum Icon {
11    Trash,
12}
13
14/// Possible filetype values for filetypes field of
15/// [`FileInput`](crate::blocks::elements::FileInput).
16/// See [this](https://docs.slack.dev/reference/objects/file-object#types).
17#[derive(Debug, Copy, Clone, Serialize, PartialEq)]
18#[serde(rename_all = "snake_case")]
19pub enum FileType {
20    /// Auto Detect Type
21    Auto,
22    /// Plain Text
23    Text,
24    /// Illustrator File
25    Ai,
26    /// APK
27    Apk,
28    /// AppleScript
29    Applescript,
30    /// Binary
31    Binary,
32    /// Bitmap
33    Bmp,
34    /// BoxNote
35    Boxnote,
36    /// C
37    C,
38    /// C#
39    Csharp,
40    /// C++
41    Cpp,
42    /// Css
43    Css,
44    /// CSV
45    Csv,
46    /// Clojure
47    Clojure,
48    /// CoffeeScript
49    Coffeescript,
50    /// ColdFusion
51    Cfm,
52    /// D
53    D,
54    /// Dart
55    Dart,
56    /// Diff
57    Diff,
58    /// Word Document
59    Doc,
60    /// Word document
61    Docx,
62    /// Docker
63    Dockerfile,
64    /// Word template
65    Dotx,
66    /// Email
67    Email,
68    /// EPS
69    Eps,
70    /// EPUB
71    Epub,
72    /// Erlang
73    Erlang,
74    /// Flash FLA
75    Fla,
76    /// Flash video
77    Flv,
78    /// F#
79    Fsharp,
80    /// Fortran
81    Fortran,
82    /// GDocs Document
83    Gdoc,
84    /// GDocs Drawing
85    Gdraw,
86    /// GIF
87    Gif,
88    /// Go
89    Go,
90    /// GDocs Presentation
91    Gpres,
92    /// Groovy
93    Groovy,
94    /// GDocs Spreadsheet
95    Gsheet,
96    /// Gzip
97    Gzip,
98    /// HTML
99    Html,
100    /// Handlebars
101    Handlebars,
102    /// Haskell
103    Haskell,
104    /// Haxe
105    Haxe,
106    /// InDesign Document
107    Indd,
108    /// Java
109    Java,
110    /// JavaScript
111    Javascript,
112    /// JPEG
113    Jpg,
114    /// JSON
115    Json,
116    /// Keynote Document
117    Keynote,
118    /// Kotlin
119    Kotlin,
120    /// LaTeX/sTeX
121    Latex,
122    /// Lisp
123    Lisp,
124    /// Lua
125    Lua,
126    /// MPEG 4 audio
127    M4a,
128    /// Markdown (raw)
129    Markdown,
130    /// MATLAB
131    Matlab,
132    /// MHTML
133    Mhtml,
134    /// Matroska video
135    Mkv,
136    /// QuickTime video
137    Mov,
138    /// MP3
139    Mp3,
140    /// MPEG 4 video
141    Mp4,
142    /// MPEG video
143    Mpg,
144    /// MUMPS
145    Mumps,
146    /// Numbers Document
147    Numbers,
148    /// NZB
149    Nzb,
150    /// Objective-C
151    Objc,
152    /// OCaml
153    Ocaml,
154    /// OpenDocument Drawing
155    Odg,
156    /// OpenDocument Image
157    Odi,
158    /// OpenDocument Presentation
159    Odp,
160    /// OpenDocument Spreadsheet
161    Ods,
162    /// OpenDocument Text
163    Odt,
164    /// Ogg Vorbis
165    Ogg,
166    /// Ogg video
167    Ogv,
168    /// Pages Document
169    Pages,
170    /// Pascal
171    Pascal,
172    /// PDF
173    Pdf,
174    /// Perl
175    Perl,
176    /// PHP
177    Php,
178    /// Pig
179    Pig,
180    /// PNG
181    Png,
182    /// Slack Post
183    Post,
184    /// PowerShell
185    Powershell,
186    /// PowerPoint presentation
187    Ppt,
188    /// PowerPoint presentation
189    Pptx,
190    /// Photoshop Document
191    Psd,
192    /// Puppet
193    Puppet,
194    /// Python
195    Python,
196    /// Quartz Composer Composition
197    Qtz,
198    /// R
199    R,
200    /// Rich Text File
201    Rtf,
202    /// Ruby
203    Ruby,
204    /// Rust
205    Rust,
206    /// SQL
207    Sql,
208    /// Sass
209    Sass,
210    /// Scala
211    Scala,
212    /// Scheme
213    Scheme,
214    /// Sketch File
215    Sketch,
216    /// Shell
217    Shell,
218    /// Smalltalk
219    Smalltalk,
220    /// SVG
221    Svg,
222    /// Flash SWF
223    Swf,
224    /// Swift
225    Swift,
226    /// Tarball
227    Tar,
228    /// TIFF
229    Tiff,
230    /// TSV
231    Tsv,
232    /// VB.NET
233    Vb,
234    /// VBScript
235    Vbscript,
236    /// vCard
237    Vcard,
238    /// Velocity
239    Velocity,
240    /// Verilog
241    Verilog,
242    /// Waveform audio
243    Wav,
244    /// WebM
245    Webm,
246    /// Windows Media Video
247    Wmv,
248    /// Excel spreadsheet
249    Xls,
250    /// Excel spreadsheet
251    Xlsx,
252    /// Excel Spreadsheet (Binary, Macro Enabled)
253    Xlsb,
254    /// Excel Spreadsheet (Macro Enabled)
255    Xlsm,
256    /// Excel template
257    Xltx,
258    /// XML
259    Xml,
260    /// YAML
261    Yaml,
262    /// Zip
263    Zip,
264}
265
266/// Button object to be set to the `positive_buttons` and `negative_buttons`
267/// fields of [`FeedbackButtons`](crate::blocks::elements::FeedbackButtons) object.
268///
269/// # Fields and Validations
270///
271/// For more details, see the [official
272/// documentation](https://docs.slack.dev/reference/block-kit/block-elements/feedback-buttons-element).
273///
274/// | Field | Type | Required | Validation |
275/// |-------|------|----------|------------|
276/// | text | [Text]<[Plain]> | Yes | Max length 75 characters |
277/// | value | String | Yes | Max length 2000 characters |
278/// | accessibility_label | String | No | Max length 75 characters |
279///
280/// # Example
281///
282/// ```
283/// use slack_messaging::plain_text;
284/// use slack_messaging::blocks::elements::types::FeedbackButton;
285/// # use std::error::Error;
286///
287/// # fn try_main() -> Result<(), Box<dyn Error>> {
288/// let button = FeedbackButton::builder()
289///     .text(plain_text!("Good")?)
290///     .value("positive_feedback")
291///     .accessibility_label("Mark this response as good")
292///     .build()?;
293///
294/// let expected = serde_json::json!({
295///     "text": {
296///         "type": "plain_text",
297///         "text": "Good"
298///     },
299///     "value": "positive_feedback",
300///     "accessibility_label": "Mark this response as good"
301/// });
302///
303/// let json = serde_json::to_value(button).unwrap();
304///
305/// assert_eq!(json, expected);
306///
307/// // If your object has any validation errors, the build method returns Result::Err
308/// let button = FeedbackButton::builder()
309///     .text(plain_text!("Good")?)
310///     .build();
311/// assert!(button.is_err());
312/// #     Ok(())
313/// # }
314/// # fn main() {
315/// #     try_main().unwrap()
316/// # }
317/// ```
318#[derive(Debug, Clone, Serialize, PartialEq, Builder)]
319pub struct FeedbackButton {
320    #[builder(validate("required", "text_object::max_75"))]
321    pub(crate) text: Option<Text<Plain>>,
322
323    #[builder(validate("required", "text::max_2000"))]
324    pub(crate) value: Option<String>,
325
326    #[serde(skip_serializing_if = "Option::is_none")]
327    #[builder(validate("text::max_75"))]
328    pub(crate) accessibility_label: Option<String>,
329}
330
331#[cfg(test)]
332mod tests {
333    use super::*;
334    use crate::composition_objects::test_helpers::*;
335    use crate::errors::*;
336
337    mod feedback_button {
338        use super::*;
339
340        #[test]
341        fn it_implements_builder() {
342            let expected = FeedbackButton {
343                text: Some(plain_text("Good")),
344                value: Some("positive_feedback".into()),
345                accessibility_label: Some("Mark this response as good".into()),
346            };
347
348            let val = FeedbackButton::builder()
349                .set_text(Some(plain_text("Good")))
350                .set_value(Some("positive_feedback"))
351                .set_accessibility_label(Some("Mark this response as good"))
352                .build()
353                .unwrap();
354
355            assert_eq!(val, expected);
356
357            let val = FeedbackButton::builder()
358                .text(plain_text("Good"))
359                .value("positive_feedback")
360                .accessibility_label("Mark this response as good")
361                .build()
362                .unwrap();
363
364            assert_eq!(val, expected);
365        }
366
367        #[test]
368        fn it_requires_text_field() {
369            let err = FeedbackButton::builder()
370                .value("positive_feedback")
371                .build()
372                .unwrap_err();
373            assert_eq!(err.object(), "FeedbackButton");
374
375            let errors = err.field("text");
376            assert!(errors.includes(ValidationErrorKind::Required));
377        }
378
379        #[test]
380        fn it_requires_text_less_than_75_characters_long() {
381            let err = FeedbackButton::builder()
382                .text(plain_text("a".repeat(76)))
383                .value("positive_feedback")
384                .build()
385                .unwrap_err();
386            assert_eq!(err.object(), "FeedbackButton");
387
388            let errors = err.field("text");
389            assert!(errors.includes(ValidationErrorKind::MaxTextLength(75)));
390        }
391
392        #[test]
393        fn it_requires_value_field() {
394            let err = FeedbackButton::builder()
395                .text(plain_text("Good"))
396                .build()
397                .unwrap_err();
398            assert_eq!(err.object(), "FeedbackButton");
399
400            let errors = err.field("value");
401            assert!(errors.includes(ValidationErrorKind::Required));
402        }
403
404        #[test]
405        fn it_requires_value_less_than_2000_characters_long() {
406            let err = FeedbackButton::builder()
407                .text(plain_text("Good"))
408                .value("a".repeat(2001))
409                .build()
410                .unwrap_err();
411            assert_eq!(err.object(), "FeedbackButton");
412
413            let errors = err.field("value");
414            assert!(errors.includes(ValidationErrorKind::MaxTextLength(2000)));
415        }
416
417        #[test]
418        fn it_requires_accessibility_label_less_than_75_characters_long() {
419            let err = FeedbackButton::builder()
420                .text(plain_text("Good"))
421                .value("positive_feedback")
422                .accessibility_label("a".repeat(76))
423                .build()
424                .unwrap_err();
425            assert_eq!(err.object(), "FeedbackButton");
426
427            let errors = err.field("accessibility_label");
428            assert!(errors.includes(ValidationErrorKind::MaxTextLength(75)));
429        }
430    }
431}