slack_blocks/elems/select/multi/static_.rs
1//! # Multi-select menu with static options
2//!
3//! [slack api docs 🔗](https://api.slack.com/reference/block-kit/block-elements#static_multi_select)
4//!
5//! This is the simplest form of select menu,
6//! with a static list of options passed in when defining the element.
7//!
8//! Works in [blocks 🔗]: Section, Input
9//!
10//! [slack api docs 🔗]: https://api.slack.com/reference/block-kit/block-elements#radio
11//! [blocks 🔗]: https://api.slack.com/reference/block-kit/blocks
12
13use std::borrow::Cow;
14
15use compose::{opt::NoUrl, Confirm};
16use serde::{Deserialize, Serialize};
17#[cfg(feature = "validation")]
18use validator::Validate;
19
20#[cfg(feature = "validation")]
21use crate::val_helpr::ValidationResult;
22use crate::{compose, elems::select::static_::build, text};
23
24type OptGroup<'a> = compose::OptGroup<'a, text::Plain, NoUrl>;
25type Opt<'a> = compose::Opt<'a, text::Plain, NoUrl>;
26type OptOrOptGroup<'a> = compose::OptOrOptGroup<'a, text::Plain, NoUrl>;
27
28/// # Multi-select menu with static options
29///
30/// [slack api docs 🔗](https://api.slack.com/reference/block-kit/block-elements#static_multi_select)
31///
32/// This is the simplest form of select menu,
33/// with a static list of options passed in when defining the element.
34///
35/// Works in [blocks 🔗]: Section, Input
36///
37/// [slack api docs 🔗]: https://api.slack.com/reference/block-kit/block-elements#radio
38/// [blocks 🔗]: https://api.slack.com/reference/block-kit/blocks
39#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
40#[cfg_attr(feature = "validation", derive(Validate))]
41pub struct Static<'a> {
42 #[cfg_attr(feature = "validation",
43 validate(custom = "crate::elems::select::validate::placeholder"))]
44 pub(in crate::elems::select) placeholder: text::Text,
45
46 #[cfg_attr(feature = "validation", validate(length(max = 255)))]
47 pub(in crate::elems::select) action_id: Cow<'a, str>,
48
49 #[serde(skip_serializing_if = "Option::is_none")]
50 #[cfg_attr(feature = "validation", validate(length(max = 100)))]
51 pub(in crate::elems::select) options: Option<Vec<Opt<'a>>>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
54 #[cfg_attr(feature = "validation", validate(length(max = 100)))]
55 pub(in crate::elems::select) option_groups: Option<Vec<OptGroup<'a>>>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
58 #[cfg_attr(feature = "validation", validate)]
59 pub(in crate::elems::select) confirm: Option<Confirm>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub(in crate::elems::select) initial_options:
63 Option<Cow<'a, [OptOrOptGroup<'a>]>>,
64
65 #[cfg_attr(feature = "validation", validate(range(min = 1)))]
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub(in crate::elems::select) max_selected_items: Option<u32>,
68}
69
70impl<'a> Static<'a> {
71 /// Build a new static select element
72 ///
73 /// # Examples
74 /// ```
75 /// // TODO(#130): implement once input or section can accept this
76 /// ```
77 pub fn builder() -> build::MultiStaticBuilderInit<'a> {
78 build::MultiStaticBuilderInit::new()
79 }
80
81 /// Validate that this select element agrees with Slack's model requirements
82 ///
83 /// # Errors
84 /// - If `from_placeholder_and_action_id` was called with
85 /// `placeholder` longer than 150 chars
86 /// - If `from_placeholder_and_action_id` was called with
87 /// `action_id` longer than 255 chars
88 ///
89 /// # Example
90 /// ```
91 /// use slack_blocks::elems::select;
92 ///
93 /// let placeholder = r#"Hey I really would appreciate it if you chose
94 /// a channel relatively soon, so that we can figure out
95 /// where we need to send this poll, ok? it's kind of
96 /// important that you specify where this poll should be
97 /// sent, in case we haven't made that super clear.
98 /// If you understand, could you pick a channel, already??"#;
99 ///
100 /// let select = select::multi::Static::builder().placeholder(placeholder)
101 /// .action_id("abc123")
102 /// .options(std::iter::empty())
103 /// .build();
104 ///
105 /// assert!(matches!(select.validate(), Err(_)))
106 /// ```
107 #[cfg(feature = "validation")]
108 #[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
109 pub fn validate(&self) -> ValidationResult {
110 Validate::validate(self)
111 }
112}