From 7becfbe889958af2fe34cde36807b28c4bb56f1d Mon Sep 17 00:00:00 2001 From: Kanji Tanaka Date: Fri, 3 Mar 2023 11:58:31 +0900 Subject: [PATCH 1/9] Up minor version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 0d6a6ad..dc2e721 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "slack-messaging" -version = "0.2.2" +version = "0.3.0" authors = ["kaicoh "] edition = "2021" keywords = ["slack", "messaging", "webhook"] From a646b692544b13a7fda3daefdc2dd504d5cba3e3 Mon Sep 17 00:00:00 2001 From: kaicoh Date: Sat, 6 Apr 2024 02:23:32 +0900 Subject: [PATCH 2/9] Fix Text object --- src/attachment.rs | 10 +- src/blocks/actions.rs | 12 +- src/blocks/context.rs | 10 +- src/blocks/divider.rs | 6 +- src/blocks/elements/button.rs | 49 +--- src/blocks/elements/checkbox_group.rs | 18 +- src/blocks/elements/confirmation_dialog.rs | 53 ++-- src/blocks/elements/datepicker.rs | 20 +- src/blocks/elements/datetimepicker.rs | 12 +- .../elements/dispatch_action_configuration.rs | 8 +- src/blocks/elements/email_input.rs | 20 +- src/blocks/elements/filter.rs | 16 +- src/blocks/elements/image.rs | 8 +- .../elements/multi_select_conversations.rs | 48 +--- src/blocks/elements/multi_select_externals.rs | 44 +-- .../elements/multi_select_public_channels.rs | 44 +-- .../elements/multi_select_static_options.rs | 52 +--- src/blocks/elements/multi_select_users.rs | 44 +-- src/blocks/elements/number_input.rs | 50 +--- src/blocks/elements/opt.rs | 68 +---- src/blocks/elements/opt_group.rs | 38 +-- src/blocks/elements/overflow_menu.rs | 12 +- src/blocks/elements/plain_text_input.rs | 48 +--- src/blocks/elements/radio_button_group.rs | 16 +- src/blocks/elements/select_conversations.rs | 50 +--- src/blocks/elements/select_externals.rs | 42 +-- src/blocks/elements/select_public_channels.rs | 46 +-- src/blocks/elements/select_static_options.rs | 48 +--- src/blocks/elements/select_users.rs | 40 +-- src/blocks/elements/text.rs | 268 +++++++++++------- src/blocks/elements/timepicker.rs | 42 +-- src/blocks/elements/url_input.rs | 40 +-- src/blocks/header.rs | 36 +-- src/blocks/image.rs | 39 +-- src/blocks/input.rs | 82 +----- src/blocks/section.rs | 122 +------- src/blocks/video.rs | 89 +----- src/fmt/date.rs | 12 +- src/lib.rs | 2 +- src/macros.rs | 72 +++-- src/message.rs | 32 +-- 41 files changed, 561 insertions(+), 1207 deletions(-) diff --git a/src/attachment.rs b/src/attachment.rs index 9f71679..760da7e 100644 --- a/src/attachment.rs +++ b/src/attachment.rs @@ -9,7 +9,7 @@ use serde::Serialize; /// See also [Context](crate::blocks::Context), [Section](crate::blocks::Section) /// and [any other blocks](crate::blocks) to know how to build these blocks. /// -/// ``` +/// ```ignore /// use slack_messaging::Attachment; /// use slack_messaging::blocks::{Context, Section}; /// use slack_messaging::blocks::elements::{Image, Text}; @@ -123,7 +123,7 @@ pub struct Attachment { impl Attachment { /// Constructs an Attachment. /// - /// ``` + /// ```ignore /// use slack_messaging::Attachment; /// use serde_json::json; /// @@ -139,7 +139,7 @@ impl Attachment { /// Sets color field. /// - /// ``` + /// ```ignore /// use slack_messaging::Attachment; /// use serde_json::json; /// @@ -161,7 +161,7 @@ impl Attachment { /// Sets blocks field directly. The argument is a vector composed from any objects /// that can transform into the enum [Block](crate::blocks::Block). /// - /// ``` + /// ```ignore /// use slack_messaging::Attachment; /// use slack_messaging::blocks::{Context, Section}; /// use slack_messaging::blocks::elements::Text; @@ -207,7 +207,7 @@ impl Attachment { /// Adds an object to blocks field. The argument is an any object /// that can transform into the enum [Block](crate::blocks::Block). /// - /// ``` + /// ```ignore /// use slack_messaging::Attachment; /// use slack_messaging::blocks::{Context, Section}; /// use slack_messaging::blocks::elements::Text; diff --git a/src/blocks/actions.rs b/src/blocks/actions.rs index 0fe4475..25c6438 100644 --- a/src/blocks/actions.rs +++ b/src/blocks/actions.rs @@ -13,7 +13,7 @@ use serde::Serialize; /// /// The following is reproduction of [the 1st sample actions](https://api.slack.com/reference/block-kit/blocks#actions_examples). /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Actions; /// use slack_messaging::blocks::elements::{Button, SelectStaticOptions, Opt}; /// use serde_json::json; @@ -103,7 +103,7 @@ use serde::Serialize; /// /// And the following is the [2nd sample actions](https://api.slack.com/reference/block-kit/blocks#actions_examples). /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Actions; /// use slack_messaging::blocks::elements::{Button, DatePicker, Opt, OverflowMenu}; /// use serde_json::json; @@ -234,7 +234,7 @@ impl Default for Actions { impl Actions { /// Constructs an Actions block. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Actions; /// use serde_json::json; /// @@ -256,7 +256,7 @@ impl Actions { /// Sets elements field directly. The argument is a vector composed from any objects /// that can transform into the enum [ActionsElement]. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Actions; /// use slack_messaging::blocks::elements::{Button, SelectStaticOptions, Opt}; /// use serde_json::json; @@ -332,7 +332,7 @@ impl Actions { /// Adds an object to elements field. The argument is an any object /// that can transform into the enum [ActionsElement]. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Actions; /// use slack_messaging::blocks::elements::{Button, DatePicker}; /// use serde_json::json; @@ -389,7 +389,7 @@ impl Actions { /// Sets block_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Actions; /// use serde_json::json; /// diff --git a/src/blocks/context.rs b/src/blocks/context.rs index b685da2..565cc8c 100644 --- a/src/blocks/context.rs +++ b/src/blocks/context.rs @@ -8,7 +8,7 @@ use serde::Serialize; /// /// The following is reproduction of [the sample context](https://api.slack.com/reference/block-kit/blocks#context_examples). /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Context; /// use slack_messaging::blocks::elements::{Image, Text}; /// use serde_json::json; @@ -66,7 +66,7 @@ impl Default for Context { impl Context { /// Constructs a Context block. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Context; /// use serde_json::json; /// @@ -88,7 +88,7 @@ impl Context { /// Sets elements field directly. The argument is a vector composed from any objects /// that can transform into the enum [ContextElement]. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Context; /// use slack_messaging::blocks::elements::{Image, Text}; /// use serde_json::json; @@ -130,7 +130,7 @@ impl Context { /// Adds an object to elements field. The argument is an any object /// that can transform into the enum [ContextElement]. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Context; /// use slack_messaging::blocks::elements::{Image, Text}; /// use serde_json::json; @@ -172,7 +172,7 @@ impl Context { /// Sets block_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Context; /// use serde_json::json; /// diff --git a/src/blocks/divider.rs b/src/blocks/divider.rs index 9a01a3c..e5a4e4d 100644 --- a/src/blocks/divider.rs +++ b/src/blocks/divider.rs @@ -5,7 +5,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Divider; /// use serde_json::json; /// @@ -41,7 +41,7 @@ impl Default for Divider { impl Divider { /// Constructs a Divider block. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Divider; /// use serde_json::json; /// @@ -61,7 +61,7 @@ impl Divider { /// Sets block_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Divider; /// use serde_json::json; /// diff --git a/src/blocks/elements/button.rs b/src/blocks/elements/button.rs index f2b2e29..2fe53c0 100644 --- a/src/blocks/elements/button.rs +++ b/src/blocks/elements/button.rs @@ -1,4 +1,5 @@ use super::{ConfirmationDialog, Text}; +use crate::plain_text; use serde::Serialize; /// [Button element](https://api.slack.com/reference/block-kit/block-elements#button) @@ -6,7 +7,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; /// @@ -59,7 +60,7 @@ impl Default for Button { fn default() -> Self { Self { kind: "button", - text: Text::plain(""), + text: plain_text!(""), action_id: "".into(), url: None, value: None, @@ -73,7 +74,7 @@ impl Default for Button { impl Button { /// Constructs a Button element. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; /// @@ -99,7 +100,7 @@ impl Button { /// Sets text field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Button, Text}; /// use serde_json::json; /// @@ -123,35 +124,9 @@ impl Button { Self { text, ..self } } - /// Sets text field from string. This is a shorthand for `set_text` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::Button; - /// use serde_json::json; - /// - /// let button = Button::new().text("Click Me"); - /// - /// let expected = json!({ - /// "type": "button", - /// "text": { - /// "type": "plain_text", - /// "text": "Click Me", - /// "emoji": true - /// }, - /// "action_id": "" - /// }); - /// - /// let button_json = serde_json::to_value(button).unwrap(); - /// - /// assert_eq!(button_json, expected); - /// ``` - pub fn text>(self, text: T) -> Self { - self.set_text(Text::plain(text)) - } - /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; /// @@ -180,7 +155,7 @@ impl Button { /// Sets url field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; /// @@ -210,7 +185,7 @@ impl Button { /// Sets value field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; /// @@ -240,7 +215,7 @@ impl Button { /// Sets primary to style field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; /// @@ -270,7 +245,7 @@ impl Button { /// Sets danger to style field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; /// @@ -300,7 +275,7 @@ impl Button { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Button, ConfirmationDialog}; /// use serde_json::json; /// @@ -358,7 +333,7 @@ impl Button { /// Sets accessibility_label field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; /// diff --git a/src/blocks/elements/checkbox_group.rs b/src/blocks/elements/checkbox_group.rs index 97e9a65..9ffa3fd 100644 --- a/src/blocks/elements/checkbox_group.rs +++ b/src/blocks/elements/checkbox_group.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::{CheckboxGroup, Opt}; /// use serde_json::json; /// @@ -81,7 +81,7 @@ impl Default for CheckboxGroup { impl CheckboxGroup { /// Constructs a Checkbox group with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::CheckboxGroup; /// use serde_json::json; /// @@ -103,7 +103,7 @@ impl CheckboxGroup { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::CheckboxGroup; /// use serde_json::json; /// @@ -128,7 +128,7 @@ impl CheckboxGroup { /// Sets options field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{CheckboxGroup, Opt}; /// use serde_json::json; /// @@ -173,7 +173,7 @@ impl CheckboxGroup { /// Adds Opt object to options field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{CheckboxGroup, Opt}; /// use serde_json::json; /// @@ -209,7 +209,7 @@ impl CheckboxGroup { /// Sets initial_options field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{CheckboxGroup, Opt}; /// use serde_json::json; /// @@ -258,7 +258,7 @@ impl CheckboxGroup { /// Adds Opt object to initial_options field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{CheckboxGroup, Opt}; /// use serde_json::json; /// @@ -301,7 +301,7 @@ impl CheckboxGroup { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{CheckboxGroup, ConfirmationDialog}; /// use serde_json::json; /// @@ -355,7 +355,7 @@ impl CheckboxGroup { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{CheckboxGroup, Opt}; /// use serde_json::json; /// diff --git a/src/blocks/elements/confirmation_dialog.rs b/src/blocks/elements/confirmation_dialog.rs index 362481e..e258fa6 100644 --- a/src/blocks/elements/confirmation_dialog.rs +++ b/src/blocks/elements/confirmation_dialog.rs @@ -1,4 +1,5 @@ use super::Text; +use crate::plain_text; use serde::Serialize; /// [Confirmation dialog object](https://api.slack.com/reference/block-kit/composition-objects#confirm) @@ -6,7 +7,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::ConfirmationDialog; /// use serde_json::json; /// @@ -60,10 +61,10 @@ pub struct ConfirmationDialog { impl Default for ConfirmationDialog { fn default() -> Self { Self { - title: Text::plain(""), - text: Text::plain(""), - confirm: Text::plain(""), - deny: Text::plain(""), + title: plain_text!(""), + text: plain_text!(""), + confirm: plain_text!(""), + deny: plain_text!(""), style: None, } } @@ -72,7 +73,7 @@ impl Default for ConfirmationDialog { impl ConfirmationDialog { /// Constructs a Confirmation dialog object with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::ConfirmationDialog; /// use serde_json::{json, Value}; /// @@ -92,7 +93,7 @@ impl ConfirmationDialog { /// Sets title field with plain_text object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::ConfirmationDialog; /// use serde_json::{json, Value}; /// @@ -103,16 +104,13 @@ impl ConfirmationDialog { /// /// assert_eq!(confirm_json["title"]["text"], Value::String("Are you sure?".into())); /// ``` - pub fn set_title>(self, title: T) -> Self { - Self { - title: Text::plain(title), - ..self - } + pub fn set_title(self, title: Text) -> Self { + Self { title, ..self } } /// Sets text field with plain_text object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::ConfirmationDialog; /// use serde_json::{json, Value}; /// @@ -123,16 +121,13 @@ impl ConfirmationDialog { /// /// assert_eq!(confirm_json["text"]["text"], Value::String("Wouldn't you prefer a good game of _chess_?".into())); /// ``` - pub fn set_text>(self, text: T) -> Self { - Self { - text: Text::plain(text), - ..self - } + pub fn set_text(self, text: Text) -> Self { + Self { text, ..self } } /// Sets confirm field with plain_text object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::ConfirmationDialog; /// use serde_json::{json, Value}; /// @@ -143,16 +138,13 @@ impl ConfirmationDialog { /// /// assert_eq!(confirm_json["confirm"]["text"], Value::String("Do it".into())); /// ``` - pub fn set_confirm>(self, confirm: T) -> Self { - Self { - confirm: Text::plain(confirm), - ..self - } + pub fn set_confirm(self, confirm: Text) -> Self { + Self { confirm, ..self } } /// Sets deny field with plain_text object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::ConfirmationDialog; /// use serde_json::{json, Value}; /// @@ -163,16 +155,13 @@ impl ConfirmationDialog { /// /// assert_eq!(confirm_json["deny"]["text"], Value::String("Stop, I've changed my mind!".into())); /// ``` - pub fn set_deny>(self, deny: T) -> Self { - Self { - deny: Text::plain(deny), - ..self - } + pub fn set_deny(self, deny: Text) -> Self { + Self { deny, ..self } } /// Sets style field as "primary". /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::ConfirmationDialog; /// use serde_json::{json, Value}; /// @@ -191,7 +180,7 @@ impl ConfirmationDialog { /// Sets style field as "danger". /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::ConfirmationDialog; /// use serde_json::{json, Value}; /// diff --git a/src/blocks/elements/datepicker.rs b/src/blocks/elements/datepicker.rs index 068e360..a24beb4 100644 --- a/src/blocks/elements/datepicker.rs +++ b/src/blocks/elements/datepicker.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::DatePicker; /// use serde_json::json; /// @@ -66,7 +66,7 @@ impl Default for DatePicker { impl DatePicker { /// Constructs a Date picker element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatePicker; /// use serde_json::json; /// @@ -87,7 +87,7 @@ impl DatePicker { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatePicker; /// use serde_json::json; /// @@ -111,7 +111,7 @@ impl DatePicker { /// Sets initial_date field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatePicker; /// use serde_json::json; /// @@ -136,7 +136,7 @@ impl DatePicker { /// Sets confirm field with ConfirmationDialog. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{DatePicker, ConfirmationDialog}; /// use serde_json::json; /// @@ -189,7 +189,7 @@ impl DatePicker { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatePicker; /// use serde_json::json; /// @@ -214,7 +214,7 @@ impl DatePicker { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{DatePicker, Text}; /// use serde_json::json; /// @@ -244,7 +244,7 @@ impl DatePicker { /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatePicker; /// use serde_json::json; /// @@ -265,7 +265,7 @@ impl DatePicker { /// /// assert_eq!(datepicker_json, expected); /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) + pub fn placeholder(self, placeholder: Text) -> Self { + self.set_placeholder(placeholder) } } diff --git a/src/blocks/elements/datetimepicker.rs b/src/blocks/elements/datetimepicker.rs index 96aaa4b..b1771db 100644 --- a/src/blocks/elements/datetimepicker.rs +++ b/src/blocks/elements/datetimepicker.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::DatetimePicker; /// use serde_json::json; /// @@ -56,7 +56,7 @@ impl Default for DatetimePicker { impl DatetimePicker { /// Constructs a Datetime picker element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatetimePicker; /// use serde_json::json; /// @@ -77,7 +77,7 @@ impl DatetimePicker { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatetimePicker; /// use serde_json::json; /// @@ -102,7 +102,7 @@ impl DatetimePicker { /// Sets initial_date_time field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatetimePicker; /// use serde_json::json; /// @@ -127,7 +127,7 @@ impl DatetimePicker { /// Sets confirm field with ConfirmationDialog. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{ConfirmationDialog, DatetimePicker}; /// use serde_json::json; /// @@ -180,7 +180,7 @@ impl DatetimePicker { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DatetimePicker; /// use serde_json::json; /// diff --git a/src/blocks/elements/dispatch_action_configuration.rs b/src/blocks/elements/dispatch_action_configuration.rs index 66eebaf..e0d5ece 100644 --- a/src/blocks/elements/dispatch_action_configuration.rs +++ b/src/blocks/elements/dispatch_action_configuration.rs @@ -16,7 +16,7 @@ pub enum TriggerAction { /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; /// use serde_json::json; /// @@ -43,7 +43,7 @@ pub struct DispatchActionConfiguration { impl DispatchActionConfiguration { /// Constructs a Dispatch action configuration. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::DispatchActionConfiguration; /// use serde_json::json; /// @@ -63,7 +63,7 @@ impl DispatchActionConfiguration { /// Sets trigger_actions_on field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; /// use serde_json::json; /// @@ -94,7 +94,7 @@ impl DispatchActionConfiguration { /// Adds trigger_action to trigger_actions_on field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; /// use serde_json::json; /// diff --git a/src/blocks/elements/email_input.rs b/src/blocks/elements/email_input.rs index fc0b6cf..879da63 100644 --- a/src/blocks/elements/email_input.rs +++ b/src/blocks/elements/email_input.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::EmailInput; /// use serde_json::json; /// @@ -64,7 +64,7 @@ impl Default for EmailInput { impl EmailInput { /// Constructs a Email Input element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::EmailInput; /// use serde_json::json; /// @@ -85,7 +85,7 @@ impl EmailInput { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::EmailInput; /// use serde_json::json; /// @@ -109,7 +109,7 @@ impl EmailInput { /// Sets initial_value field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::EmailInput; /// use serde_json::json; /// @@ -134,7 +134,7 @@ impl EmailInput { /// Sets dispatch_action_config field with DispatchActionConfiguration. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{EmailInput, DispatchActionConfiguration, /// TriggerAction}; /// use serde_json::json; @@ -168,7 +168,7 @@ impl EmailInput { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::EmailInput; /// use serde_json::json; /// @@ -193,7 +193,7 @@ impl EmailInput { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{EmailInput, Text}; /// use serde_json::json; /// @@ -222,7 +222,7 @@ impl EmailInput { /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::EmailInput; /// use serde_json::json; /// @@ -242,7 +242,7 @@ impl EmailInput { /// /// assert_eq!(email_json, expected); /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) + pub fn placeholder(self, placeholder: Text) -> Self { + self.set_placeholder(placeholder) } } diff --git a/src/blocks/elements/filter.rs b/src/blocks/elements/filter.rs index 1cac412..eeac9f0 100644 --- a/src/blocks/elements/filter.rs +++ b/src/blocks/elements/filter.rs @@ -15,7 +15,7 @@ pub enum Conversation { /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::{Filter, Conversation}; /// use serde_json::json; /// @@ -51,7 +51,7 @@ pub struct Filter { impl Filter { /// Constructs a Filter object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Filter; /// use serde_json::json; /// @@ -69,7 +69,7 @@ impl Filter { /// Sets include field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Filter, Conversation}; /// use serde_json::json; /// @@ -98,7 +98,7 @@ impl Filter { /// Adds conversation to include field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Filter, Conversation}; /// use serde_json::json; /// @@ -128,7 +128,7 @@ impl Filter { /// Sets exclude_external_shared_channels field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Filter, Conversation}; /// use serde_json::json; /// @@ -152,7 +152,7 @@ impl Filter { /// Sets true to exclude_external_shared_channels field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Filter, Conversation}; /// use serde_json::json; /// @@ -173,7 +173,7 @@ impl Filter { /// Sets exclude_bot_users field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Filter, Conversation}; /// use serde_json::json; /// @@ -197,7 +197,7 @@ impl Filter { /// Sets true to exclude_bot_users field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Filter, Conversation}; /// use serde_json::json; /// diff --git a/src/blocks/elements/image.rs b/src/blocks/elements/image.rs index 9ba066d..e51b18f 100644 --- a/src/blocks/elements/image.rs +++ b/src/blocks/elements/image.rs @@ -5,7 +5,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::Image; /// use serde_json::json; /// @@ -46,7 +46,7 @@ impl Default for Image { impl Image { /// Constructs a Image element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Image; /// use serde_json::json; /// @@ -68,7 +68,7 @@ impl Image { /// Sets image_url field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Image; /// use serde_json::json; /// @@ -93,7 +93,7 @@ impl Image { /// Sets alt_text field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Image; /// use serde_json::json; /// diff --git a/src/blocks/elements/multi_select_conversations.rs b/src/blocks/elements/multi_select_conversations.rs index e65fa81..63316a4 100644 --- a/src/blocks/elements/multi_select_conversations.rs +++ b/src/blocks/elements/multi_select_conversations.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::MultiSelectConversations; /// use serde_json::json; /// @@ -76,7 +76,7 @@ impl Default for MultiSelectConversations { impl MultiSelectConversations { /// Constructs a Multi-select menu Conversations list element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectConversations; /// use serde_json::json; /// @@ -97,7 +97,7 @@ impl MultiSelectConversations { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectConversations; /// use serde_json::json; /// @@ -121,7 +121,7 @@ impl MultiSelectConversations { /// Sets initial_conversations field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectConversations; /// use serde_json::json; /// @@ -149,7 +149,7 @@ impl MultiSelectConversations { /// Adds string to initial_conversations field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectConversations; /// use serde_json::json; /// @@ -180,7 +180,7 @@ impl MultiSelectConversations { /// Sets default_to_current_conversation field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectConversations; /// use serde_json::json; /// @@ -206,7 +206,7 @@ impl MultiSelectConversations { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectConversations, ConfirmationDialog}; /// use serde_json::json; /// @@ -259,7 +259,7 @@ impl MultiSelectConversations { /// Sets max_selected_items field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectConversations; /// use serde_json::json; /// @@ -285,7 +285,7 @@ impl MultiSelectConversations { /// Sets filter field with Filter object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectConversations, Filter, Conversation}; /// use serde_json::json; /// @@ -322,7 +322,7 @@ impl MultiSelectConversations { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectConversations; /// use serde_json::json; /// @@ -347,7 +347,7 @@ impl MultiSelectConversations { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectConversations, Text}; /// use serde_json::json; /// @@ -374,30 +374,4 @@ impl MultiSelectConversations { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::MultiSelectConversations; - /// use serde_json::json; - /// - /// let menu = MultiSelectConversations::new().placeholder("Select conversations"); - /// - /// let expected = json!({ - /// "type": "multi_conversations_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select conversations", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/multi_select_externals.rs b/src/blocks/elements/multi_select_externals.rs index de38911..fd7d5c8 100644 --- a/src/blocks/elements/multi_select_externals.rs +++ b/src/blocks/elements/multi_select_externals.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::MultiSelectExternals; /// use serde_json::json; /// @@ -74,7 +74,7 @@ impl Default for MultiSelectExternals { impl MultiSelectExternals { /// Constructs a Multi-select menu External data source element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectExternals; /// use serde_json::json; /// @@ -119,7 +119,7 @@ impl MultiSelectExternals { /// Sets initial_options field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectExternals, Opt}; /// use serde_json::json; /// @@ -167,7 +167,7 @@ impl MultiSelectExternals { /// Adds Opt object to initial_options field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectExternals, Opt}; /// use serde_json::json; /// @@ -209,7 +209,7 @@ impl MultiSelectExternals { /// Sets min_query_length field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectExternals; /// use serde_json::json; /// @@ -235,7 +235,7 @@ impl MultiSelectExternals { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectExternals, ConfirmationDialog}; /// use serde_json::json; /// @@ -288,7 +288,7 @@ impl MultiSelectExternals { /// Sets max_selected_items field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectExternals; /// use serde_json::json; /// @@ -314,7 +314,7 @@ impl MultiSelectExternals { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectExternals; /// use serde_json::json; /// @@ -340,7 +340,7 @@ impl MultiSelectExternals { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectExternals, Text}; /// use serde_json::json; /// @@ -367,30 +367,4 @@ impl MultiSelectExternals { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::MultiSelectExternals; - /// use serde_json::json; - /// - /// let menu = MultiSelectExternals::new().placeholder("Select items"); - /// - /// let expected = json!({ - /// "type": "multi_external_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select items", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/multi_select_public_channels.rs b/src/blocks/elements/multi_select_public_channels.rs index 5b4cdbd..b6a1f45 100644 --- a/src/blocks/elements/multi_select_public_channels.rs +++ b/src/blocks/elements/multi_select_public_channels.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::MultiSelectPublicChannels; /// use serde_json::json; /// @@ -68,7 +68,7 @@ impl Default for MultiSelectPublicChannels { impl MultiSelectPublicChannels { /// Constructs a Multi-select menu Public channels element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectPublicChannels; /// use serde_json::json; /// @@ -89,7 +89,7 @@ impl MultiSelectPublicChannels { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectPublicChannels; /// use serde_json::json; /// @@ -113,7 +113,7 @@ impl MultiSelectPublicChannels { /// Sets initial_channels field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectPublicChannels; /// use serde_json::json; /// @@ -141,7 +141,7 @@ impl MultiSelectPublicChannels { /// Adds string to initial_channels field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectPublicChannels; /// use serde_json::json; /// @@ -172,7 +172,7 @@ impl MultiSelectPublicChannels { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectPublicChannels, ConfirmationDialog}; /// use serde_json::json; /// @@ -225,7 +225,7 @@ impl MultiSelectPublicChannels { /// Sets max_selected_items field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectPublicChannels; /// use serde_json::json; /// @@ -251,7 +251,7 @@ impl MultiSelectPublicChannels { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectPublicChannels; /// use serde_json::json; /// @@ -277,7 +277,7 @@ impl MultiSelectPublicChannels { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectPublicChannels, Text}; /// use serde_json::json; /// @@ -304,30 +304,4 @@ impl MultiSelectPublicChannels { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::MultiSelectPublicChannels; - /// use serde_json::json; - /// - /// let menu = MultiSelectPublicChannels::new().placeholder("Select channels"); - /// - /// let expected = json!({ - /// "type": "multi_channels_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select channels", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/multi_select_static_options.rs b/src/blocks/elements/multi_select_static_options.rs index 2274b6c..1d7a7f5 100644 --- a/src/blocks/elements/multi_select_static_options.rs +++ b/src/blocks/elements/multi_select_static_options.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -100,7 +100,7 @@ impl Default for MultiSelectStaticOptions { impl MultiSelectStaticOptions { /// Constructs a Multi-select menu Static options element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -121,7 +121,7 @@ impl MultiSelectStaticOptions { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -147,7 +147,7 @@ impl MultiSelectStaticOptions { /// Sets options field directly and removes option_groups field. /// (Either options or option_groups field exists.) /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -197,7 +197,7 @@ impl MultiSelectStaticOptions { /// Adds Opt object to options field and removes option_groups field. /// (Either options or option_groups field exists.) /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -238,7 +238,7 @@ impl MultiSelectStaticOptions { /// Sets option_groups field directly and removes options field. /// (Either options or option_groups field exists.) /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt, OptGroup}; /// use serde_json::json; /// @@ -335,7 +335,7 @@ impl MultiSelectStaticOptions { /// Adds OptGroup object to option_groups field and removes options field. /// (Either options or option_groups field exists.) /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt, OptGroup}; /// use serde_json::json; /// @@ -401,7 +401,7 @@ impl MultiSelectStaticOptions { /// Sets initial_options field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -449,7 +449,7 @@ impl MultiSelectStaticOptions { /// Adds Opt object to initial_options field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -491,7 +491,7 @@ impl MultiSelectStaticOptions { /// Sets confirm field with ConfirmationDialog. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, ConfirmationDialog}; /// use serde_json::json; /// @@ -544,7 +544,7 @@ impl MultiSelectStaticOptions { /// Sets max_selected_items field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectStaticOptions; /// use serde_json::json; /// @@ -570,7 +570,7 @@ impl MultiSelectStaticOptions { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectStaticOptions; /// use serde_json::json; /// @@ -595,7 +595,7 @@ impl MultiSelectStaticOptions { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectStaticOptions, Text}; /// use serde_json::json; /// @@ -622,30 +622,4 @@ impl MultiSelectStaticOptions { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::MultiSelectStaticOptions; - /// use serde_json::json; - /// - /// let menu = MultiSelectStaticOptions::new().placeholder("Select items"); - /// - /// let expected = json!({ - /// "type": "multi_static_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select items", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/multi_select_users.rs b/src/blocks/elements/multi_select_users.rs index 3af4ef1..47446ba 100644 --- a/src/blocks/elements/multi_select_users.rs +++ b/src/blocks/elements/multi_select_users.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::MultiSelectUsers; /// use serde_json::json; /// @@ -72,7 +72,7 @@ impl Default for MultiSelectUsers { impl MultiSelectUsers { /// Constructs a Multi-select menu User list element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectUsers; /// use serde_json::json; /// @@ -93,7 +93,7 @@ impl MultiSelectUsers { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectUsers; /// use serde_json::json; /// @@ -117,7 +117,7 @@ impl MultiSelectUsers { /// Sets initial_users field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectUsers; /// use serde_json::json; /// @@ -145,7 +145,7 @@ impl MultiSelectUsers { /// Adds string to initial_users field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectUsers; /// use serde_json::json; /// @@ -175,7 +175,7 @@ impl MultiSelectUsers { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectUsers, ConfirmationDialog}; /// use serde_json::json; /// @@ -228,7 +228,7 @@ impl MultiSelectUsers { /// Sets max_selected_items field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectUsers; /// use serde_json::json; /// @@ -253,7 +253,7 @@ impl MultiSelectUsers { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::MultiSelectUsers; /// use serde_json::json; /// @@ -278,7 +278,7 @@ impl MultiSelectUsers { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{MultiSelectUsers, Text}; /// use serde_json::json; /// @@ -304,30 +304,4 @@ impl MultiSelectUsers { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::MultiSelectUsers; - /// use serde_json::json; - /// - /// let menu = MultiSelectUsers::new().placeholder("Select users"); - /// - /// let expected = json!({ - /// "type": "multi_users_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select users", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/number_input.rs b/src/blocks/elements/number_input.rs index d2ee524..5a38800 100644 --- a/src/blocks/elements/number_input.rs +++ b/src/blocks/elements/number_input.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -72,7 +72,7 @@ impl Default for NumberInput { impl NumberInput { /// Constructs a Number input element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -93,7 +93,7 @@ impl NumberInput { /// Sets is_decimal_allowed field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -117,7 +117,7 @@ impl NumberInput { /// Sets true to is_decimal_allowed field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -138,7 +138,7 @@ impl NumberInput { /// Sets false to is_decimal_allowed field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -159,7 +159,7 @@ impl NumberInput { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -184,7 +184,7 @@ impl NumberInput { /// Sets initial_value field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -209,7 +209,7 @@ impl NumberInput { /// Sets min_value field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -234,7 +234,7 @@ impl NumberInput { /// Sets max_value field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -259,7 +259,7 @@ impl NumberInput { /// Sets dispatch_action_config field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{NumberInput, DispatchActionConfiguration, /// TriggerAction}; /// use serde_json::json; @@ -292,7 +292,7 @@ impl NumberInput { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::NumberInput; /// use serde_json::json; /// @@ -317,7 +317,7 @@ impl NumberInput { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{NumberInput, Text}; /// use serde_json::json; /// @@ -343,30 +343,4 @@ impl NumberInput { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::NumberInput; - /// use serde_json::json; - /// - /// let num = NumberInput::new().placeholder("How old are you?"); - /// - /// let expected = json!({ - /// "type": "number_input", - /// "is_decimal_allowed": false, - /// "placeholder": { - /// "type": "plain_text", - /// "text": "How old are you?", - /// "emoji": true - /// } - /// }); - /// - /// let num_json = serde_json::to_value(num).unwrap(); - /// - /// assert_eq!(num_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/opt.rs b/src/blocks/elements/opt.rs index 2eaaf37..0d1fb8f 100644 --- a/src/blocks/elements/opt.rs +++ b/src/blocks/elements/opt.rs @@ -1,4 +1,5 @@ use super::Text; +use crate::plain_text; use serde::Serialize; /// [Option object](https://api.slack.com/reference/block-kit/composition-objects#option) @@ -6,7 +7,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::{Opt, Text}; /// use serde_json::json; /// @@ -43,7 +44,7 @@ pub struct Opt { impl Default for Opt { fn default() -> Self { Self { - text: Text::plain(""), + text: plain_text!(""), value: "".into(), description: None, url: None, @@ -54,7 +55,7 @@ impl Default for Opt { impl Opt { /// Constructs a Option object with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Opt; /// use serde_json::{json, Value}; /// @@ -71,58 +72,9 @@ impl Opt { Self::default() } - /// Constructs a Option object with plain_text object. - /// - /// ``` - /// use slack_messaging::blocks::elements::Opt; - /// use serde_json::json; - /// - /// let option = Opt::plain("This is a plain text."); - /// - /// let expected = json!({ - /// "text": { - /// "type": "plain_text", - /// "text": "This is a plain text.", - /// "emoji": true - /// }, - /// "value": "" - /// }); - /// - /// let option_json = serde_json::to_value(option).unwrap(); - /// - /// assert_eq!(option_json, expected); - /// ``` - pub fn plain>(text: T) -> Self { - Self::new().set_text(Text::plain(text)) - } - - /// Constructs a Option object with mrkdwn object. - /// - /// ``` - /// use slack_messaging::blocks::elements::Opt; - /// use serde_json::json; - /// - /// let option = Opt::mrkdwn("This is a ~plain~markdown text."); - /// - /// let expected = json!({ - /// "text": { - /// "type": "mrkdwn", - /// "text": "This is a ~plain~markdown text." - /// }, - /// "value": "" - /// }); - /// - /// let option_json = serde_json::to_value(option).unwrap(); - /// - /// assert_eq!(option_json, expected); - /// ``` - pub fn mrkdwn>(text: T) -> Self { - Self::new().set_text(Text::mrkdwn(text)) - } - /// Sets text field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{Opt, Text}; /// use serde_json::json; /// @@ -148,7 +100,7 @@ impl Opt { /// Sets text field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Opt; /// use serde_json::json; /// @@ -176,7 +128,7 @@ impl Opt { /// Sets description field with plain_text object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Opt; /// use serde_json::json; /// @@ -200,16 +152,16 @@ impl Opt { /// /// assert_eq!(option_json, expected); /// ``` - pub fn set_description>(self, description: T) -> Self { + pub fn set_description(self, description: Text) -> Self { Self { - description: Some(Text::plain(description)), + description: Some(description), ..self } } /// Sets url field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::Opt; /// use serde_json::{json, Value}; /// diff --git a/src/blocks/elements/opt_group.rs b/src/blocks/elements/opt_group.rs index 02eb927..f32f410 100644 --- a/src/blocks/elements/opt_group.rs +++ b/src/blocks/elements/opt_group.rs @@ -1,5 +1,6 @@ use super::Opt; use super::Text; +use crate::plain_text; use serde::Serialize; /// [Option group object](https://api.slack.com/reference/block-kit/composition-objects#option_group) @@ -7,7 +8,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::{OptGroup, Opt}; /// use serde_json::json; /// @@ -58,7 +59,7 @@ pub struct OptGroup { impl Default for OptGroup { fn default() -> Self { Self { - label: Text::plain(""), + label: plain_text!(""), options: vec![], } } @@ -67,7 +68,7 @@ impl Default for OptGroup { impl OptGroup { /// Constructs a Option group object with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::OptGroup; /// use serde_json::json; /// @@ -92,7 +93,7 @@ impl OptGroup { /// Sets label field with Text object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{OptGroup, Text}; /// use serde_json::json; /// @@ -115,34 +116,9 @@ impl OptGroup { Self { label, ..self } } - /// Sets label field with string. This is a shorthand for `set_label` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::OptGroup; - /// use serde_json::json; - /// - /// let options = OptGroup::new().label("Group One"); - /// - /// let expected = json!({ - /// "label": { - /// "type": "plain_text", - /// "text": "Group One", - /// "emoji": true - /// }, - /// "options": [] - /// }); - /// - /// let options_json = serde_json::to_value(options).unwrap(); - /// - /// assert_eq!(options_json, expected); - /// ``` - pub fn label>(self, label: T) -> Self { - self.set_label(Text::plain(label)) - } - /// Sets options field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{OptGroup, Opt}; /// use serde_json::json; /// @@ -189,7 +165,7 @@ impl OptGroup { /// Adds Option object to options field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{OptGroup, Opt}; /// use serde_json::json; /// diff --git a/src/blocks/elements/overflow_menu.rs b/src/blocks/elements/overflow_menu.rs index 80c57a1..3043d7b 100644 --- a/src/blocks/elements/overflow_menu.rs +++ b/src/blocks/elements/overflow_menu.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::{OverflowMenu, Opt}; /// use serde_json::json; /// @@ -74,7 +74,7 @@ impl Default for OverflowMenu { impl OverflowMenu { /// Constructs a Overflow menu element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::OverflowMenu; /// use serde_json::json; /// @@ -95,7 +95,7 @@ impl OverflowMenu { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::OverflowMenu; /// use serde_json::json; /// @@ -119,7 +119,7 @@ impl OverflowMenu { /// Sets options field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{OverflowMenu, Opt}; /// use serde_json::json; /// @@ -164,7 +164,7 @@ impl OverflowMenu { /// Adds Opt object to options field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{OverflowMenu, Opt}; /// use serde_json::json; /// @@ -198,7 +198,7 @@ impl OverflowMenu { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{OverflowMenu, ConfirmationDialog}; /// use serde_json::json; /// diff --git a/src/blocks/elements/plain_text_input.rs b/src/blocks/elements/plain_text_input.rs index 195beaf..c73b88e 100644 --- a/src/blocks/elements/plain_text_input.rs +++ b/src/blocks/elements/plain_text_input.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -78,7 +78,7 @@ impl Default for PlainTextInput { impl PlainTextInput { /// Constructs a Plain-text input element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -99,7 +99,7 @@ impl PlainTextInput { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -123,7 +123,7 @@ impl PlainTextInput { /// Sets initial_value field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -148,7 +148,7 @@ impl PlainTextInput { /// Sets multiline field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -173,7 +173,7 @@ impl PlainTextInput { /// Sets true to multiline field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -195,7 +195,7 @@ impl PlainTextInput { /// Sets min_length field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -220,7 +220,7 @@ impl PlainTextInput { /// Sets max_length field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -245,7 +245,7 @@ impl PlainTextInput { /// Sets dispatch_action_config field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{PlainTextInput, DispatchActionConfiguration, /// TriggerAction}; /// use serde_json::json; @@ -277,7 +277,7 @@ impl PlainTextInput { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; /// @@ -302,7 +302,7 @@ impl PlainTextInput { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{PlainTextInput, Text}; /// use serde_json::json; /// @@ -329,30 +329,4 @@ impl PlainTextInput { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::PlainTextInput; - /// use serde_json::json; - /// - /// let plain = PlainTextInput::new().placeholder("Enter some plain text"); - /// - /// let expected = json!({ - /// "type": "plain_text_input", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Enter some plain text", - /// "emoji": true - /// } - /// }); - /// - /// let plain_json = serde_json::to_value(plain).unwrap(); - /// - /// assert_eq!(plain_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/radio_button_group.rs b/src/blocks/elements/radio_button_group.rs index 8575469..6762467 100644 --- a/src/blocks/elements/radio_button_group.rs +++ b/src/blocks/elements/radio_button_group.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::{RadioButtonGroup, Opt}; /// use serde_json::json; /// @@ -81,7 +81,7 @@ impl Default for RadioButtonGroup { impl RadioButtonGroup { /// Constructs a Radio button group element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::RadioButtonGroup; /// use serde_json::json; /// @@ -103,7 +103,7 @@ impl RadioButtonGroup { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::RadioButtonGroup; /// use serde_json::json; /// @@ -128,7 +128,7 @@ impl RadioButtonGroup { /// Sets options field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{RadioButtonGroup, Opt}; /// use serde_json::json; /// @@ -173,7 +173,7 @@ impl RadioButtonGroup { /// Adds Opt object to options field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{RadioButtonGroup, Opt}; /// use serde_json::json; /// @@ -209,7 +209,7 @@ impl RadioButtonGroup { /// Sets initial_option field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{RadioButtonGroup, Opt}; /// use serde_json::json; /// @@ -245,7 +245,7 @@ impl RadioButtonGroup { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{RadioButtonGroup, ConfirmationDialog}; /// use serde_json::json; /// @@ -299,7 +299,7 @@ impl RadioButtonGroup { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::RadioButtonGroup; /// use serde_json::json; /// diff --git a/src/blocks/elements/select_conversations.rs b/src/blocks/elements/select_conversations.rs index b675c41..1ed4978 100644 --- a/src/blocks/elements/select_conversations.rs +++ b/src/blocks/elements/select_conversations.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -76,7 +76,7 @@ impl Default for SelectConversations { impl SelectConversations { /// Constructs a Select menu of conversations element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -97,7 +97,7 @@ impl SelectConversations { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -121,7 +121,7 @@ impl SelectConversations { /// Sets initial_conversation field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -147,7 +147,7 @@ impl SelectConversations { /// Sets default_to_current_conversation field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -173,7 +173,7 @@ impl SelectConversations { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectConversations, ConfirmationDialog}; /// use serde_json::json; /// @@ -226,7 +226,7 @@ impl SelectConversations { /// Sets response_url_enabled field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -251,7 +251,7 @@ impl SelectConversations { /// Sets true to response_url_enabled field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -273,7 +273,7 @@ impl SelectConversations { /// Sets false to response_url_enabled field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -295,7 +295,7 @@ impl SelectConversations { /// Sets filter field with Filter object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectConversations, Filter, Conversation}; /// use serde_json::json; /// @@ -332,7 +332,7 @@ impl SelectConversations { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectConversations; /// use serde_json::json; /// @@ -357,7 +357,7 @@ impl SelectConversations { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectConversations, Text}; /// use serde_json::json; /// @@ -384,30 +384,4 @@ impl SelectConversations { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::SelectConversations; - /// use serde_json::json; - /// - /// let menu = SelectConversations::new().placeholder("Select an item"); - /// - /// let expected = json!({ - /// "type": "conversations_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select an item", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/select_externals.rs b/src/blocks/elements/select_externals.rs index 9965f49..6ec54ad 100644 --- a/src/blocks/elements/select_externals.rs +++ b/src/blocks/elements/select_externals.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::SelectExternals; /// use serde_json::json; /// @@ -70,7 +70,7 @@ impl Default for SelectExternals { impl SelectExternals { /// Constructs a Select menu of external data source element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectExternals; /// use serde_json::json; /// @@ -91,7 +91,7 @@ impl SelectExternals { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectExternals; /// use serde_json::json; /// @@ -115,7 +115,7 @@ impl SelectExternals { /// Sets initial_option field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectExternals, Opt}; /// use serde_json::json; /// @@ -150,7 +150,7 @@ impl SelectExternals { /// Sets min_query_length field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectExternals, Opt}; /// use serde_json::json; /// @@ -175,7 +175,7 @@ impl SelectExternals { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectExternals, ConfirmationDialog}; /// use serde_json::json; /// @@ -228,7 +228,7 @@ impl SelectExternals { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectExternals; /// use serde_json::json; /// @@ -253,7 +253,7 @@ impl SelectExternals { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectExternals, Text}; /// use serde_json::json; /// @@ -280,30 +280,4 @@ impl SelectExternals { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::SelectExternals; - /// use serde_json::json; - /// - /// let menu = SelectExternals::new().placeholder("Select an item"); - /// - /// let expected = json!({ - /// "type": "external_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select an item", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/select_public_channels.rs b/src/blocks/elements/select_public_channels.rs index f35b643..fac4304 100644 --- a/src/blocks/elements/select_public_channels.rs +++ b/src/blocks/elements/select_public_channels.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::SelectPublicChannels; /// use serde_json::json; /// @@ -68,7 +68,7 @@ impl Default for SelectPublicChannels { impl SelectPublicChannels { /// Constructs a Select menu of public channels element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectPublicChannels; /// use serde_json::json; /// @@ -89,7 +89,7 @@ impl SelectPublicChannels { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectPublicChannels; /// use serde_json::json; /// @@ -113,7 +113,7 @@ impl SelectPublicChannels { /// Sets initial_channel field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectPublicChannels; /// use serde_json::json; /// @@ -138,7 +138,7 @@ impl SelectPublicChannels { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectPublicChannels, ConfirmationDialog}; /// use serde_json::json; /// @@ -191,7 +191,7 @@ impl SelectPublicChannels { /// Sets response_url_enabled field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectPublicChannels; /// use serde_json::json; /// @@ -216,7 +216,7 @@ impl SelectPublicChannels { /// Sets true to response_url_enabled field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectPublicChannels; /// use serde_json::json; /// @@ -238,7 +238,7 @@ impl SelectPublicChannels { /// Sets false to response_url_enabled field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectPublicChannels; /// use serde_json::json; /// @@ -260,7 +260,7 @@ impl SelectPublicChannels { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectPublicChannels; /// use serde_json::json; /// @@ -285,7 +285,7 @@ impl SelectPublicChannels { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectPublicChannels, Text}; /// use serde_json::json; /// @@ -312,30 +312,4 @@ impl SelectPublicChannels { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::SelectPublicChannels; - /// use serde_json::json; - /// - /// let menu = SelectPublicChannels::new().placeholder("Select an item"); - /// - /// let expected = json!({ - /// "type": "channels_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select an item", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/select_static_options.rs b/src/blocks/elements/select_static_options.rs index ede5a2a..573377f 100644 --- a/src/blocks/elements/select_static_options.rs +++ b/src/blocks/elements/select_static_options.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ingore /// use slack_messaging::blocks::elements::{SelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -96,7 +96,7 @@ impl Default for SelectStaticOptions { impl SelectStaticOptions { /// Constructs a Select menu of static options element with empty values. /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::SelectStaticOptions; /// use serde_json::json; /// @@ -117,7 +117,7 @@ impl SelectStaticOptions { /// Sets action_id field. /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::SelectStaticOptions; /// use serde_json::json; /// @@ -142,7 +142,7 @@ impl SelectStaticOptions { /// Sets options field directly and removes option_groups field. /// (Either options or option_groups field exists.) /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::{SelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -192,7 +192,7 @@ impl SelectStaticOptions { /// Adds Opt object to options field and removes option_groups field. /// (Either options or option_groups field exists.) /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::{SelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -233,7 +233,7 @@ impl SelectStaticOptions { /// Sets option_groups field directly and removes options field. /// (Either options or option_groups field exists.) /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::{SelectStaticOptions, Opt, OptGroup}; /// use serde_json::json; /// @@ -330,7 +330,7 @@ impl SelectStaticOptions { /// Adds OptGroup object to option_groups field and removes options field. /// (Either options or option_groups field exists.) /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::{SelectStaticOptions, Opt, OptGroup}; /// use serde_json::json; /// @@ -396,7 +396,7 @@ impl SelectStaticOptions { /// Sets initial_option field. /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::{SelectStaticOptions, Opt}; /// use serde_json::json; /// @@ -431,7 +431,7 @@ impl SelectStaticOptions { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::{SelectStaticOptions, ConfirmationDialog}; /// use serde_json::json; /// @@ -484,7 +484,7 @@ impl SelectStaticOptions { /// Sets focus_on_load field. /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::SelectStaticOptions; /// use serde_json::json; /// @@ -509,7 +509,7 @@ impl SelectStaticOptions { /// Sets placeholder field. /// - /// ``` + /// ```ingore /// use slack_messaging::blocks::elements::{SelectStaticOptions, Text}; /// use serde_json::json; /// @@ -536,30 +536,4 @@ impl SelectStaticOptions { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::SelectStaticOptions; - /// use serde_json::json; - /// - /// let menu = SelectStaticOptions::new().placeholder("Select an item"); - /// - /// let expected = json!({ - /// "type": "static_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select an item", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/select_users.rs b/src/blocks/elements/select_users.rs index 1e0a7bb..3a7a428 100644 --- a/src/blocks/elements/select_users.rs +++ b/src/blocks/elements/select_users.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::SelectUsers; /// use serde_json::json; /// @@ -64,7 +64,7 @@ impl Default for SelectUsers { impl SelectUsers { /// Constructs a Select menu of users element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectUsers; /// use serde_json::json; /// @@ -85,7 +85,7 @@ impl SelectUsers { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectUsers; /// use serde_json::json; /// @@ -109,7 +109,7 @@ impl SelectUsers { /// Sets initial_user field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectUsers; /// use serde_json::json; /// @@ -134,7 +134,7 @@ impl SelectUsers { /// Sets confirm field with ConfirmationDialog object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectUsers, ConfirmationDialog}; /// use serde_json::json; /// @@ -187,7 +187,7 @@ impl SelectUsers { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::SelectUsers; /// use serde_json::json; /// @@ -212,7 +212,7 @@ impl SelectUsers { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{SelectUsers, Text}; /// use serde_json::json; /// @@ -239,30 +239,4 @@ impl SelectUsers { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::SelectUsers; - /// use serde_json::json; - /// - /// let menu = SelectUsers::new().placeholder("Select an item"); - /// - /// let expected = json!({ - /// "type": "users_select", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select an item", - /// "emoji": true - /// } - /// }); - /// - /// let menu_json = serde_json::to_value(menu).unwrap(); - /// - /// assert_eq!(menu_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/elements/text.rs b/src/blocks/elements/text.rs index a4dd371..03918f1 100644 --- a/src/blocks/elements/text.rs +++ b/src/blocks/elements/text.rs @@ -11,36 +11,38 @@ const TYPE_MRKDWN: &str = "mrkdwn"; /// ## type plain_text /// /// ``` -/// use slack_messaging::blocks::elements::Text; -/// use serde_json::json; +/// # use slack_messaging::blocks::elements::Text; +/// let text = Text::builder() +/// .plain_text() +/// .set_text("Hello, World!") +/// .build(); /// -/// let text = Text::plain("Hello, World!"); -/// let text_json = serde_json::to_value(text).unwrap(); +/// let json = serde_json::to_value(text).unwrap(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "type": "plain_text", -/// "text": "Hello, World!", -/// "emoji": true +/// "text": "Hello, World!" /// }); /// -/// assert_eq!(text_json, expected); +/// assert_eq!(json, expected); /// ``` /// /// ## type mrkdwn /// /// ``` -/// use slack_messaging::blocks::elements::Text; -/// use serde_json::json; -/// -/// let text = Text::mrkdwn("Hello, World!"); -/// let text_json = serde_json::to_value(text).unwrap(); +/// # use slack_messaging::blocks::elements::Text; +/// let text = Text::builder() +/// .mrkdwn() +/// .set_text("Hello, World!") +/// .build(); +/// let json = serde_json::to_value(text).unwrap(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "type": "mrkdwn", /// "text": "Hello, World!", /// }); /// -/// assert_eq!(text_json, expected); +/// assert_eq!(json, expected); /// ``` #[derive(Debug, Clone, Serialize)] pub struct Text { @@ -57,80 +59,105 @@ pub struct Text { } impl Text { - /// Constructs a `plain_text` object and enables emoji. + /// Constructs a [`TextBuilder`]. + pub fn builder() -> TextBuilder { + TextBuilder::default() + } +} + +impl PartialEq for Text { + fn eq(&self, other: &Self) -> bool { + if self.kind != other.kind || self.text.as_str() != other.text.as_str() { + return false; + } + + match self.kind { + TYPE_PLAIN => self.emoji == other.emoji, + TYPE_MRKDWN => self.verbatim == other.verbatim, + _ => false, + } + } +} + +#[derive(Debug, Default)] +pub struct TextBuilder { + kind: Option<&'static str>, + text: Option, + emoji: Option, + verbatim: Option, +} + +impl TextBuilder { + /// Turns self into a `plain_text` text object. Either `plain_text` or `mrkdwn` method must + /// be called before the `build` method is called. /// /// ``` - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; - /// - /// let text = Text::plain("hello world"); + /// # use slack_messaging::blocks::elements::Text; + /// let text = Text::builder() + /// .plain_text() + /// .set_text("hello world") + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "plain_text", /// "text": "hello world", - /// "emoji": true /// }); /// - /// let text_json = serde_json::to_value(text).unwrap(); - /// - /// assert_eq!(text_json, expected); + /// let json = serde_json::to_value(text).unwrap(); + /// assert_eq!(json, expected); /// ``` - pub fn plain>(text: T) -> Self { + pub fn plain_text(self) -> Self { Self { - kind: TYPE_PLAIN, - text: text.into(), - emoji: Some(true), - verbatim: None, + kind: Some(TYPE_PLAIN), + ..self } } - /// Constructs a `mrkdwn` object. + /// Turns self into a `mrkdwn` text object. Either `plain_text` or `mrkdwn` method must + /// be called before the `build` method is called. /// /// ``` - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; + /// # use slack_messaging::blocks::elements::Text; + /// let text = Text::builder() + /// .mrkdwn() + /// .set_text("hello world") + /// .build(); /// - /// let text = Text::mrkdwn("hello world"); - /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "mrkdwn", /// "text": "hello world", /// }); /// - /// let text_json = serde_json::to_value(text).unwrap(); - /// - /// assert_eq!(text_json, expected); + /// let json = serde_json::to_value(text).unwrap(); + /// assert_eq!(json, expected); /// ``` - pub fn mrkdwn>(text: T) -> Self { + pub fn mrkdwn(self) -> Self { Self { - kind: TYPE_MRKDWN, - text: text.into(), - emoji: None, - verbatim: None, + kind: Some(TYPE_MRKDWN), + ..self } } - /// Sets text field. + /// Sets text field. This method must be called before the `build` method is called. /// /// ``` - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; - /// - /// let text = Text::plain("hello world").set_text("hi!"); + /// # use slack_messaging::blocks::elements::Text; + /// let text = Text::builder() + /// .plain_text() + /// .set_text("hello world") + /// .build(); /// - /// let expected = json!({ - /// "type": "plain_text", - /// "text": "hi!", - /// "emoji": true + /// let expected = serde_json::json!({ + /// "type": "plain_text", + /// "text": "hello world", /// }); /// - /// let text_json = serde_json::to_value(text).unwrap(); - /// - /// assert_eq!(text_json, expected); + /// let json = serde_json::to_value(text).unwrap(); + /// assert_eq!(json, expected); /// ``` - pub fn set_text>(self, text: T) -> Self { + pub fn set_text(self, text: impl Into) -> Self { Self { - text: text.into(), + text: Some(text.into()), ..self } } @@ -138,20 +165,21 @@ impl Text { /// Sets emoji field. /// /// ``` - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; + /// # use slack_messaging::blocks::elements::Text; + /// let text = Text::builder() + /// .plain_text() + /// .set_emoji(true) + /// .set_text("😊") + /// .build(); /// - /// let text = Text::plain("hello world").set_emoji(false); - /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "plain_text", - /// "text": "hello world", - /// "emoji": false + /// "text": "😊", + /// "emoji": true /// }); /// - /// let text_json = serde_json::to_value(text).unwrap(); - /// - /// assert_eq!(text_json, expected); + /// let json = serde_json::to_value(text).unwrap(); + /// assert_eq!(json, expected); /// ``` pub fn set_emoji(self, emoji: bool) -> Self { Self { @@ -163,20 +191,21 @@ impl Text { /// Sets verbatim field. /// /// ``` - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; - /// - /// let text = Text::mrkdwn("hello world").set_verbatim(true); + /// # use slack_messaging::blocks::elements::Text; + /// let text = Text::builder() + /// .mrkdwn() + /// .set_text("hello world") + /// .set_verbatim(true) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "mrkdwn", /// "text": "hello world", /// "verbatim": true /// }); /// - /// let text_json = serde_json::to_value(text).unwrap(); - /// - /// assert_eq!(text_json, expected); + /// let json = serde_json::to_value(text).unwrap(); + /// assert_eq!(json, expected); /// ``` pub fn set_verbatim(self, verbatim: bool) -> Self { Self { @@ -184,18 +213,30 @@ impl Text { ..self } } -} - -impl PartialEq for Text { - fn eq(&self, other: &Self) -> bool { - if self.kind != other.kind || self.text.as_str() != other.text.as_str() { - return false; - } - match self.kind { - TYPE_PLAIN => self.emoji.unwrap_or(false) == other.emoji.unwrap_or(false), - TYPE_MRKDWN => self.verbatim.unwrap_or(false) == other.verbatim.unwrap_or(false), - _ => false, + /// Build a [`Text`] object. This method will panic if either `type` of `text` is not set. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Text; + /// let text = Text::builder() + /// .plain_text() + /// .set_text("hello world") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "type": "plain_text", + /// "text": "hello world", + /// }); + /// + /// let json = serde_json::to_value(text).unwrap(); + /// assert_eq!(json, expected); + /// ``` + pub fn build(self) -> Text { + Text { + kind: self.kind.expect("text type must be set"), + text: self.text.expect("text must be set"), + emoji: self.emoji, + verbatim: self.verbatim, } } } @@ -206,11 +247,13 @@ mod tests { #[test] fn it_equals_with_same_type_and_text() { - let plain_0 = Text::plain("Hello"); - let plain_1 = Text::plain("Hello"); + let plain_0 = Text::builder().plain_text().set_text("Hello").build(); + let plain_1 = Text::builder().plain_text().set_text("Hello").build(); + let plain_2 = Text::builder().plain_text().set_text("hello").build(); - let mrkdwn_0 = Text::mrkdwn("Hello"); - let mrkdwn_1 = Text::mrkdwn("Hello"); + let mrkdwn_0 = Text::builder().mrkdwn().set_text("Hello").build(); + let mrkdwn_1 = Text::builder().mrkdwn().set_text("Hello").build(); + let mrkdwn_2 = Text::builder().mrkdwn().set_text("hello").build(); assert_eq!(plain_0, plain_1); assert_eq!(mrkdwn_0, mrkdwn_1); @@ -219,30 +262,57 @@ mod tests { assert_ne!(plain_0, mrkdwn_1); assert_ne!(plain_1, mrkdwn_0); assert_ne!(plain_1, mrkdwn_1); + + assert_ne!(plain_0, plain_2); + assert_ne!(mrkdwn_0, mrkdwn_2); } #[test] fn it_compares_emoji_field_when_plain_text() { - let plain_0 = Text::plain("Hello").set_emoji(false); - let plain_1 = Text::plain("Hello"); + let plain_0 = Text::builder() + .plain_text() + .set_text("Hello") + .set_emoji(false) + .build(); + let plain_1 = Text::builder().plain_text().set_text("Hello").build(); assert_ne!(plain_0, plain_1); - let plain_0 = Text::plain("Hello").set_emoji(false); - let plain_1 = Text::plain("Hello").set_emoji(false); + let plain_0 = Text::builder() + .plain_text() + .set_text("Hello") + .set_emoji(false) + .build(); + let plain_1 = Text::builder() + .plain_text() + .set_text("Hello") + .set_emoji(false) + .build(); assert_eq!(plain_0, plain_1); } #[test] fn it_compares_verbatim_field_when_mrkdwn() { - let mrkdwn_0 = Text::mrkdwn("Hello").set_verbatim(true); - let mrkdwn_1 = Text::mrkdwn("Hello"); + let mrkdwn_0 = Text::builder() + .mrkdwn() + .set_text("Hello") + .set_verbatim(true) + .build(); + let mrkdwn_1 = Text::builder().mrkdwn().set_text("Hello").build(); assert_ne!(mrkdwn_0, mrkdwn_1); - let mrkdwn_0 = Text::mrkdwn("Hello").set_verbatim(true); - let mrkdwn_1 = Text::mrkdwn("Hello").set_verbatim(true); + let mrkdwn_0 = Text::builder() + .mrkdwn() + .set_text("Hello") + .set_verbatim(true) + .build(); + let mrkdwn_1 = Text::builder() + .mrkdwn() + .set_text("Hello") + .set_verbatim(true) + .build(); assert_eq!(mrkdwn_0, mrkdwn_1); } diff --git a/src/blocks/elements/timepicker.rs b/src/blocks/elements/timepicker.rs index 1862d67..badd324 100644 --- a/src/blocks/elements/timepicker.rs +++ b/src/blocks/elements/timepicker.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::TimePicker; /// use serde_json::json; /// @@ -72,7 +72,7 @@ impl Default for TimePicker { impl TimePicker { /// Constructs a Time picker element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::TimePicker; /// use serde_json::json; /// @@ -93,7 +93,7 @@ impl TimePicker { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::TimePicker; /// use serde_json::json; /// @@ -117,7 +117,7 @@ impl TimePicker { /// Sets initial_time field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::TimePicker; /// use serde_json::json; /// @@ -142,7 +142,7 @@ impl TimePicker { /// Sets confirm field with ConfirmationDialog. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{TimePicker, ConfirmationDialog}; /// use serde_json::json; /// @@ -195,7 +195,7 @@ impl TimePicker { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::TimePicker; /// use serde_json::json; /// @@ -220,7 +220,7 @@ impl TimePicker { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{TimePicker, Text}; /// use serde_json::json; /// @@ -248,35 +248,9 @@ impl TimePicker { } } - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::TimePicker; - /// use serde_json::json; - /// - /// let timepicker = TimePicker::new().placeholder("Select a time"); - /// - /// let expected = json!({ - /// "type": "timepicker", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Select a time", - /// "emoji": true - /// } - /// }); - /// - /// let timepicker_json = serde_json::to_value(timepicker).unwrap(); - /// - /// assert_eq!(timepicker_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } - /// Sets timezone field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::TimePicker; /// use serde_json::json; /// diff --git a/src/blocks/elements/url_input.rs b/src/blocks/elements/url_input.rs index 706fe3d..a0d5f89 100644 --- a/src/blocks/elements/url_input.rs +++ b/src/blocks/elements/url_input.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::elements::UrlInput; /// use serde_json::json; /// @@ -64,7 +64,7 @@ impl Default for UrlInput { impl UrlInput { /// Constructs a URL input element with empty values. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::UrlInput; /// use serde_json::json; /// @@ -85,7 +85,7 @@ impl UrlInput { /// Sets action_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::UrlInput; /// use serde_json::json; /// @@ -109,7 +109,7 @@ impl UrlInput { /// Sets initial_value field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::UrlInput; /// use serde_json::json; /// @@ -134,7 +134,7 @@ impl UrlInput { /// Sets dispatch_action_config field with DispatchActionConfiguration object. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{UrlInput, DispatchActionConfiguration, /// TriggerAction}; /// use serde_json::json; @@ -167,7 +167,7 @@ impl UrlInput { /// Sets focus_on_load field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::UrlInput; /// use serde_json::json; /// @@ -192,7 +192,7 @@ impl UrlInput { /// Sets placeholder field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::elements::{UrlInput, Text}; /// use serde_json::json; /// @@ -219,30 +219,4 @@ impl UrlInput { ..self } } - - /// Sets placeholder field from string. This is a shorthand for `set_placeholder` method. - /// - /// ``` - /// use slack_messaging::blocks::elements::UrlInput; - /// use serde_json::json; - /// - /// let url = UrlInput::new().placeholder("Enter url"); - /// - /// let expected = json!({ - /// "type": "url_text_input", - /// "action_id": "", - /// "placeholder": { - /// "type": "plain_text", - /// "text": "Enter url", - /// "emoji": true - /// } - /// }); - /// - /// let url_json = serde_json::to_value(url).unwrap(); - /// - /// assert_eq!(url_json, expected); - /// ``` - pub fn placeholder>(self, placeholder: T) -> Self { - self.set_placeholder(Text::plain(placeholder)) - } } diff --git a/src/blocks/header.rs b/src/blocks/header.rs index ec5bb60..17f8c9f 100644 --- a/src/blocks/header.rs +++ b/src/blocks/header.rs @@ -1,4 +1,5 @@ use super::elements::Text; +use crate::plain_text; use serde::Serialize; /// [Header block](https://api.slack.com/reference/block-kit/blocks#header) @@ -6,7 +7,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Header; /// use serde_json::json; /// @@ -43,7 +44,7 @@ impl Default for Header { fn default() -> Self { Self { kind: "header", - text: Text::plain(""), + text: plain_text!(""), block_id: None, } } @@ -52,7 +53,7 @@ impl Default for Header { impl Header { /// Constructs a Header block. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Header; /// use serde_json::json; /// @@ -77,7 +78,7 @@ impl Header { /// Sets text field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Header; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -102,34 +103,9 @@ impl Header { Self { text, ..self } } - /// Sets text field from string. This is a shorthand for `set_text` method. - /// - /// ``` - /// use slack_messaging::blocks::Header; - /// use serde_json::json; - /// - /// let header = Header::new().text("Budget Performance"); - /// - /// let expected = json!({ - /// "type": "header", - /// "text": { - /// "type": "plain_text", - /// "text": "Budget Performance", - /// "emoji": true - /// } - /// }); - /// - /// let header_json = serde_json::to_value(header).unwrap(); - /// - /// assert_eq!(header_json, expected); - /// ``` - pub fn text>(self, text: T) -> Self { - self.set_text(Text::plain(text)) - } - /// Sets block_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Header; /// use serde_json::json; /// diff --git a/src/blocks/image.rs b/src/blocks/image.rs index 4b40527..16a788d 100644 --- a/src/blocks/image.rs +++ b/src/blocks/image.rs @@ -6,7 +6,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Image; /// use serde_json::json; /// @@ -63,7 +63,7 @@ impl Default for Image { impl Image { /// Constructs an Image block. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Image; /// use serde_json::json; /// @@ -85,7 +85,7 @@ impl Image { /// Sets image_url field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Image; /// use serde_json::json; /// @@ -110,7 +110,7 @@ impl Image { /// Sets alt_text field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Image; /// use serde_json::json; /// @@ -135,7 +135,7 @@ impl Image { /// Sets title field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Image; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -165,36 +165,9 @@ impl Image { } } - /// Sets title field from string. This is a shorthand for `set_text` method. - /// - /// ``` - /// use slack_messaging::blocks::Image; - /// use serde_json::json; - /// - /// let image = Image::new().title("Please enjoy this photo of a kitten"); - /// - /// let expected = json!({ - /// "type": "image", - /// "title": { - /// "type": "plain_text", - /// "text": "Please enjoy this photo of a kitten", - /// "emoji": true - /// }, - /// "image_url": "", - /// "alt_text": "" - /// }); - /// - /// let image_json = serde_json::to_value(image).unwrap(); - /// - /// assert_eq!(image_json, expected); - /// ``` - pub fn title>(self, title: T) -> Self { - self.set_title(Text::plain(title)) - } - /// Sets block_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Image; /// use serde_json::json; /// diff --git a/src/blocks/input.rs b/src/blocks/input.rs index b0bac1c..12b944c 100644 --- a/src/blocks/input.rs +++ b/src/blocks/input.rs @@ -4,6 +4,7 @@ use super::elements::{ NumberInput, PlainTextInput, RadioButtonGroup, SelectConversations, SelectExternals, SelectPublicChannels, SelectStaticOptions, SelectUsers, Text, TimePicker, UrlInput, }; +use crate::plain_text; use serde::Serialize; /// [Input block](https://api.slack.com/reference/block-kit/blocks#input) @@ -11,7 +12,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Input; /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; @@ -78,7 +79,7 @@ impl Default for Input { fn default() -> Self { Self { kind: "input", - label: Text::plain(""), + label: plain_text!(""), element: None, dispatch_action: None, block_id: None, @@ -91,7 +92,7 @@ impl Default for Input { impl Input { /// Constructs an Input block. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use serde_json::json; /// @@ -117,7 +118,7 @@ impl Input { /// Sets label field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -143,36 +144,10 @@ impl Input { Self { label, ..self } } - /// Sets label field from string. This is a shorthand for `set_label` method. - /// - /// ``` - /// use slack_messaging::blocks::Input; - /// use serde_json::json; - /// - /// let input = Input::new().label("label text"); - /// - /// let expected = json!({ - /// "type": "input", - /// "label": { - /// "type": "plain_text", - /// "text": "label text", - /// "emoji": true - /// }, - /// "element": null - /// }); - /// - /// let input_json = serde_json::to_value(input).unwrap(); - /// - /// assert_eq!(input_json, expected); - /// ``` - pub fn label>(self, label: T) -> Self { - self.set_label(Text::plain(label)) - } - /// Sets an object to element field. The argument is an any object /// that can transform into the enum [InputElement]. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use slack_messaging::blocks::elements::PlainTextInput; /// use serde_json::json; @@ -208,7 +183,7 @@ impl Input { /// Sets dispatch_action field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use serde_json::json; /// @@ -239,7 +214,7 @@ impl Input { /// Sets true to dispatch_action field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use serde_json::json; /// @@ -266,7 +241,7 @@ impl Input { /// Sets block_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use serde_json::json; /// @@ -296,7 +271,7 @@ impl Input { /// Sets hint field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -330,40 +305,9 @@ impl Input { } } - /// Sets hint field from string. This is a shorthand for `set_hint` method. - /// - /// ``` - /// use slack_messaging::blocks::Input; - /// use serde_json::json; - /// - /// let input = Input::new().hint("Some hints for input"); - /// - /// let expected = json!({ - /// "type": "input", - /// "label": { - /// "type": "plain_text", - /// "text": "", - /// "emoji": true - /// }, - /// "element": null, - /// "hint": { - /// "type": "plain_text", - /// "text": "Some hints for input", - /// "emoji": true - /// }, - /// }); - /// - /// let input_json = serde_json::to_value(input).unwrap(); - /// - /// assert_eq!(input_json, expected); - /// ``` - pub fn hint>(self, hint: T) -> Self { - self.set_hint(Text::plain(hint)) - } - /// Sets optional field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use serde_json::json; /// @@ -393,7 +337,7 @@ impl Input { /// Sets true to optional field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use serde_json::json; /// @@ -420,7 +364,7 @@ impl Input { /// Sets false to optional field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Input; /// use serde_json::json; /// diff --git a/src/blocks/section.rs b/src/blocks/section.rs index b650b3a..21d3554 100644 --- a/src/blocks/section.rs +++ b/src/blocks/section.rs @@ -11,7 +11,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Section; /// use slack_messaging::blocks::elements::Image; /// use serde_json::json; @@ -89,7 +89,7 @@ impl Default for Section { impl Section { /// Constructs a Section block. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Section; /// use serde_json::json; /// @@ -109,7 +109,7 @@ impl Section { /// Sets text field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Section; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -136,60 +136,9 @@ impl Section { } } - /// Sets text field as plain text object. - /// - /// ``` - /// use slack_messaging::blocks::Section; - /// use serde_json::json; - /// - /// let section = Section::new() - /// .set_text_plain("A message *with some bold text* and _some italicized text_."); - /// - /// let expected = json!({ - /// "type": "section", - /// "text": { - /// "type": "plain_text", - /// "text": "A message *with some bold text* and _some italicized text_.", - /// "emoji": true - /// }, - /// }); - /// - /// let section_json = serde_json::to_value(section).unwrap(); - /// - /// assert_eq!(section_json, expected); - /// ``` - pub fn set_text_plain>(self, text: T) -> Self { - self.set_text(Text::plain(text)) - } - - /// Sets text field as mrkdwn text object. - /// - /// ``` - /// use slack_messaging::blocks::Section; - /// use serde_json::json; - /// - /// let section = Section::new() - /// .set_text_mrkdwn("A message *with some bold text* and _some italicized text_."); - /// - /// let expected = json!({ - /// "type": "section", - /// "text": { - /// "type": "mrkdwn", - /// "text": "A message *with some bold text* and _some italicized text_." - /// }, - /// }); - /// - /// let section_json = serde_json::to_value(section).unwrap(); - /// - /// assert_eq!(section_json, expected); - /// ``` - pub fn set_text_mrkdwn>(self, text: T) -> Self { - self.set_text(Text::mrkdwn(text)) - } - /// Sets block_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Section; /// use serde_json::json; /// @@ -214,7 +163,7 @@ impl Section { /// Sets fields field directly. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Section; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -252,7 +201,7 @@ impl Section { /// Adds Text object to fields field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Section; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -283,67 +232,10 @@ impl Section { Self { fields, ..self } } - /// Adds plain_text Text object to fields field. - /// - /// ``` - /// use slack_messaging::blocks::Section; - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; - /// - /// let section = Section::new() - /// .push_field_plain("hello world"); - /// - /// let expected = json!({ - /// "type": "section", - /// "fields": [ - /// { - /// "type": "plain_text", - /// "text": "hello world", - /// "emoji": true - /// } - /// ] - /// }); - /// - /// let section_json = serde_json::to_value(section).unwrap(); - /// - /// assert_eq!(section_json, expected); - /// ``` - pub fn push_field_plain>(self, field: T) -> Self { - self.push_field(Text::plain(field)) - } - - /// Adds mrkdwn Text object to fields field. - /// - /// ``` - /// use slack_messaging::blocks::Section; - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; - /// - /// let section = Section::new() - /// .push_field_mrkdwn("hello world"); - /// - /// let expected = json!({ - /// "type": "section", - /// "fields": [ - /// { - /// "type": "mrkdwn", - /// "text": "hello world" - /// } - /// ] - /// }); - /// - /// let section_json = serde_json::to_value(section).unwrap(); - /// - /// assert_eq!(section_json, expected); - /// ``` - pub fn push_field_mrkdwn>(self, field: T) -> Self { - self.push_field(Text::mrkdwn(field)) - } - /// Sets object to accessory field. The argument is an any object /// that can transform into the enum [Accessory]. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Section; /// use slack_messaging::blocks::elements::Button; /// use serde_json::json; diff --git a/src/blocks/video.rs b/src/blocks/video.rs index a6e3851..ec52568 100644 --- a/src/blocks/video.rs +++ b/src/blocks/video.rs @@ -1,4 +1,5 @@ use super::elements::Text; +use crate::plain_text; use serde::Serialize; /// [Video block](https://api.slack.com/reference/block-kit/blocks#video) @@ -6,7 +7,7 @@ use serde::Serialize; /// /// # Example /// -/// ``` +/// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -83,7 +84,7 @@ impl Default for Video { Self { kind: "video", alt_text: "".to_string(), - title: Text::plain(""), + title: plain_text!(""), title_url: None, thumbnail_url: "".to_string(), video_url: "".to_string(), @@ -99,7 +100,7 @@ impl Default for Video { impl Video { /// Constructs a Video block. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -127,7 +128,7 @@ impl Video { /// Sets alt_text field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -158,7 +159,7 @@ impl Video { /// Sets title field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -186,37 +187,9 @@ impl Video { Self { title, ..self } } - /// Sets title field from string. This is a shorthand for `set_title` method. - /// - /// ``` - /// use slack_messaging::blocks::Video; - /// use serde_json::json; - /// - /// let video = Video::new().title("How to use Slack."); - /// - /// let expected = json!({ - /// "type": "video", - /// "title": { - /// "type": "plain_text", - /// "text": "How to use Slack.", - /// "emoji": true - /// }, - /// "video_url": "", - /// "thumbnail_url": "", - /// "alt_text": "" - /// }); - /// - /// let video_json = serde_json::to_value(video).unwrap(); - /// - /// assert_eq!(video_json, expected); - /// ``` - pub fn title>(self, title: T) -> Self { - self.set_title(Text::plain(title)) - } - /// Sets title_url field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -249,7 +222,7 @@ impl Video { /// Sets thumbnail_url field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -281,7 +254,7 @@ impl Video { /// Sets video_url field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -313,7 +286,7 @@ impl Video { /// Sets author_name field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -346,7 +319,7 @@ impl Video { /// Sets block_id field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -379,7 +352,7 @@ impl Video { /// Sets description field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use slack_messaging::blocks::elements::Text; /// use serde_json::json; @@ -415,43 +388,9 @@ impl Video { } } - /// Sets description field from string. This is a shorthand for `set_description` method. - /// - /// ``` - /// use slack_messaging::blocks::Video; - /// use serde_json::json; - /// - /// let video = Video::new() - /// .description("Slack is a new way to communicate with your team. It's faster, better organized and more secure than email."); - /// - /// let expected = json!({ - /// "type": "video", - /// "title": { - /// "type": "plain_text", - /// "text": "", - /// "emoji": true - /// }, - /// "description": { - /// "type": "plain_text", - /// "text": "Slack is a new way to communicate with your team. It's faster, better organized and more secure than email.", - /// "emoji": true - /// }, - /// "video_url": "", - /// "thumbnail_url": "", - /// "alt_text": "" - /// }); - /// - /// let video_json = serde_json::to_value(video).unwrap(); - /// - /// assert_eq!(video_json, expected); - /// ``` - pub fn description>(self, description: T) -> Self { - self.set_description(Text::plain(description)) - } - /// Sets provider_icon_url field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// @@ -484,7 +423,7 @@ impl Video { /// Sets provider_name field. /// - /// ``` + /// ```ignore /// use slack_messaging::blocks::Video; /// use serde_json::json; /// diff --git a/src/fmt/date.rs b/src/fmt/date.rs index c1e8332..f973d2c 100644 --- a/src/fmt/date.rs +++ b/src/fmt/date.rs @@ -138,12 +138,12 @@ struct FormatReplacer { } impl FormatReplacer { - const DATE_NUM: &str = "%Y-%m-%d"; - const DATE: &str = "%B %e, %Y"; - const DATE_SHORT: &str = "%b %e, %Y"; - const DATE_LONG: &str = "%A, %B %e, %Y"; - const TIME: &str = "%l:%M %p"; - const TIME_SECS: &str = "%l:%M:%S %p"; + const DATE_NUM: &'static str = "%Y-%m-%d"; + const DATE: &'static str = "%B %e, %Y"; + const DATE_SHORT: &'static str = "%b %e, %Y"; + const DATE_LONG: &'static str = "%A, %B %e, %Y"; + const TIME: &'static str = "%l:%M %p"; + const TIME_SECS: &'static str = "%l:%M:%S %p"; fn new>(value: T) -> Self { Self { diff --git a/src/lib.rs b/src/lib.rs index 64831bc..b62d588 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ //! This is a library to support building messages for [slack messaging api](https://api.slack.com/messaging/managing). //! Using this, you can build any messages in type-safe way like following. //! -//! ``` +//! ```ignore //! use slack_messaging::Message; //! use slack_messaging::blocks::{elements::Button, Actions, Section}; //! diff --git a/src/macros.rs b/src/macros.rs index 8fad179..2d99f1c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,60 +1,82 @@ /// Constructs `plain_text` [Text](crate::blocks::elements::Text). /// /// ``` -/// use slack_messaging::plain_text; -/// use slack_messaging::blocks::elements::Text; -/// +/// # use slack_messaging::plain_text; +/// # use slack_messaging::blocks::elements::Text; /// let text = plain_text!("Hello, World!"); -/// let expected = Text::plain("Hello, World!"); +/// let expected = Text::builder() +/// .plain_text() +/// .set_text("Hello, World!") +/// .build(); /// /// assert_eq!(text, expected); /// +/// // You can use this like format! macro. /// let greet = "Hi"; /// let name = "Tanaka"; /// -/// // You can use this like format! macro. /// let text = plain_text!("{}, {}!", greet, name); -/// let expected = Text::plain("Hi, Tanaka!"); +/// let expected = Text::builder() +/// .plain_text() +/// .set_text("Hi, Tanaka!") +/// .build(); /// /// assert_eq!(text, expected); /// ``` #[macro_export] macro_rules! plain_text { ($fmt:expr) => { - $crate::blocks::elements::Text::plain(format!($fmt)) + $crate::blocks::elements::Text::builder() + .plain_text() + .set_text(format!($fmt)) + .build() }; ($fmt:expr, $($arg:tt)+) => { - $crate::blocks::elements::Text::plain(format!($fmt, $($arg)+)) + $crate::blocks::elements::Text::builder() + .plain_text() + .set_text(format!($fmt, $($arg)+)) + .build() }; } /// Constructs `mrkdwn` [Text](crate::blocks::elements::Text). /// /// ``` -/// use slack_messaging::mrkdwn; -/// use slack_messaging::blocks::elements::Text; -/// +/// # use slack_messaging::mrkdwn; +/// # use slack_messaging::blocks::elements::Text; /// let text = mrkdwn!("Hello, World!"); -/// let expected = Text::mrkdwn("Hello, World!"); +/// let expected = Text::builder() +/// .mrkdwn() +/// .set_text("Hello, World!") +/// .build(); /// /// assert_eq!(text, expected); /// +/// // You can use this like format! macro. /// let greet = "Hi"; /// let name = "Tanaka"; /// -/// // You can use this like format! macro. /// let text = mrkdwn!("{}, {}!", greet, name); -/// let expected = Text::mrkdwn("Hi, Tanaka!"); +/// let expected = Text::builder() +/// .mrkdwn() +/// .set_text("Hi, Tanaka!") +/// .build(); /// /// assert_eq!(text, expected); /// ``` #[macro_export] macro_rules! mrkdwn { ($fmt:expr) => { - $crate::blocks::elements::Text::mrkdwn(format!($fmt)) + $crate::blocks::elements::Text::builder() + .mrkdwn() + .set_text(format!($fmt)) + .build() }; ($fmt:expr, $($arg:tt)+) => { - $crate::blocks::elements::Text::mrkdwn(format!($fmt, $($arg)+)) + $crate::blocks::elements::Text::builder() + .mrkdwn() + .set_text(format!($fmt, $($arg)+)) + .build() }; } @@ -65,26 +87,36 @@ mod tests { #[test] fn it_works_macro_plain_text_given_expression() { let text = plain_text!("Hello, Tanaka!"); - assert_eq!(text, Text::plain("Hello, Tanaka!")); + let expected = Text::builder() + .plain_text() + .set_text("Hello, Tanaka!") + .build(); + assert_eq!(text, expected); } #[test] fn it_works_macro_plain_text_given_expression_and_tokens() { let name = "Tanaka"; let text = plain_text!("Hello, {}!", name); - assert_eq!(text, Text::plain("Hello, Tanaka!")); + let expected = Text::builder() + .plain_text() + .set_text("Hello, Tanaka!") + .build(); + assert_eq!(text, expected); } #[test] fn it_works_macro_mrkdwn_given_expression() { let text = mrkdwn!("Hello, Tanaka!"); - assert_eq!(text, Text::mrkdwn("Hello, Tanaka!")); + let expected = Text::builder().mrkdwn().set_text("Hello, Tanaka!").build(); + assert_eq!(text, expected); } #[test] fn it_works_macro_mrkdwn_given_expression_and_tokens() { let name = "Tanaka"; let text = mrkdwn!("Hello, {}!", name); - assert_eq!(text, Text::mrkdwn("Hello, Tanaka!")); + let expected = Text::builder().mrkdwn().set_text("Hello, Tanaka!").build(); + assert_eq!(text, expected); } } diff --git a/src/message.rs b/src/message.rs index c0e0cf3..e27f9db 100644 --- a/src/message.rs +++ b/src/message.rs @@ -9,7 +9,7 @@ use serde::Serialize; /// See also [Header](crate::blocks::Header), [Section](crate::blocks::Section) /// and [any other blocks](crate::blocks) to know how to build these blocks. /// -/// ``` +/// ```ignore /// use slack_messaging::Message; /// use slack_messaging::blocks::{Header, Section}; /// use serde_json::json; @@ -111,7 +111,7 @@ pub struct Message { impl Message { /// Constructs a Message. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -127,7 +127,7 @@ impl Message { /// Sets text field. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -152,7 +152,7 @@ impl Message { /// Sets blocks field directly. The argument is a vector composed from any objects /// that can transform into the enum [Block](crate::blocks::Block). /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use slack_messaging::blocks::{Header, Section}; /// use serde_json::json; @@ -196,7 +196,7 @@ impl Message { /// Adds an object to blocks field. The argument is an any object /// that can transform into the enum [Block](crate::blocks::Block). /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use slack_messaging::blocks::{Header, Section}; /// use serde_json::json; @@ -238,7 +238,7 @@ impl Message { /// Sets attachments field directly. See also [Attachment](crate::attachment::Attachment) /// to know how to build an Attachment. /// - /// ``` + /// ```ignore /// use slack_messaging::{Attachment, Message}; /// use slack_messaging::blocks::{Context, Section}; /// use slack_messaging::blocks::elements::Text; @@ -295,7 +295,7 @@ impl Message { /// See also [Attachment](crate::attachment::Attachment) to know /// how to build an Attachment. /// - /// ``` + /// ```ignore /// use slack_messaging::{Attachment, Message}; /// use slack_messaging::blocks::{Context, Section}; /// use slack_messaging::blocks::elements::Text; @@ -358,7 +358,7 @@ impl Message { /// Sets thread_ts field. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -382,7 +382,7 @@ impl Message { /// Sets mrkdwn field. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -405,7 +405,7 @@ impl Message { /// Sets channel field. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -428,7 +428,7 @@ impl Message { /// Sets response_type field. /// - /// ``` + /// ```ignore /// use slack_messaging::{Message, ResponseType}; /// use serde_json::json; /// @@ -452,7 +452,7 @@ impl Message { /// Sets replace_original field. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -475,7 +475,7 @@ impl Message { /// Sets true to replace_original field. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -498,7 +498,7 @@ impl Message { /// Sets delete_original field. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -521,7 +521,7 @@ impl Message { /// Sets true to delete_original field. /// - /// ``` + /// ```ignore /// use slack_messaging::Message; /// use serde_json::json; /// @@ -549,5 +549,5 @@ impl Message { pub enum ResponseType { /// Sets this if you want to publish a message to the same conversation as the interaction /// source. - InChannel + InChannel, } From 57120a6220304aad4daf296d18da2b3bf71eac7f Mon Sep 17 00:00:00 2001 From: kaicoh Date: Sat, 6 Apr 2024 15:21:49 +0900 Subject: [PATCH 3/9] Fix composable objects --- Cargo.toml | 2 +- src/blocks/elements/button.rs | 492 ++++++++++++------ src/blocks/elements/confirmation_dialog.rs | 325 ++++++++---- .../elements/dispatch_action_configuration.rs | 98 ++-- src/blocks/elements/filter.rs | 196 ++++--- src/blocks/elements/input_parameter.rs | 143 +++++ src/blocks/elements/mod.rs | 22 +- src/blocks/elements/opt.rs | 292 ++++++++--- src/blocks/elements/opt_group.rs | 203 ++++---- src/blocks/elements/slack_file.rs | 137 +++++ src/blocks/elements/text.rs | 185 +++---- src/blocks/elements/trigger.rs | 189 +++++++ src/blocks/elements/workflow.rs | 128 +++++ src/macros.rs | 38 +- 14 files changed, 1730 insertions(+), 720 deletions(-) create mode 100644 src/blocks/elements/input_parameter.rs create mode 100644 src/blocks/elements/slack_file.rs create mode 100644 src/blocks/elements/trigger.rs create mode 100644 src/blocks/elements/workflow.rs diff --git a/Cargo.toml b/Cargo.toml index dc2e721..7c772a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,10 @@ all-features = true chrono = { version = "0.4", optional = true } regex = { version = "1.7", optional = true } serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" [dev-dependencies] reqwest = { version = "0.11", features = ["json"] } -serde_json = "1.0" tokio = { version = "1", features = ["full"] } [features] diff --git a/src/blocks/elements/button.rs b/src/blocks/elements/button.rs index 2fe53c0..87e9942 100644 --- a/src/blocks/elements/button.rs +++ b/src/blocks/elements/button.rs @@ -1,5 +1,4 @@ use super::{ConfirmationDialog, Text}; -use crate::plain_text; use serde::Serialize; /// [Button element](https://api.slack.com/reference/block-kit/block-elements#button) @@ -7,29 +6,27 @@ use serde::Serialize; /// /// # Example /// -/// ```ignore -/// use slack_messaging::blocks::elements::Button; -/// use serde_json::json; -/// -/// let button = Button::new() +/// ``` +/// # use slack_messaging::blocks::elements::Button; +/// let button = Button::builder() /// .text("Click Me") -/// .set_value("click_me_123") -/// .set_action_id("button-0"); +/// .value("click_me_123") +/// .action_id("button-0") +/// .build(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", -/// "text": "Click Me", -/// "emoji": true +/// "text": "Click Me" /// }, /// "value": "click_me_123", /// "action_id": "button-0" /// }); /// -/// let button_json = serde_json::to_value(button).unwrap(); +/// let json = serde_json::to_value(button).unwrap(); /// -/// assert_eq!(button_json, expected); +/// assert_eq!(json, expected); /// ``` #[derive(Debug, Clone, Serialize)] pub struct Button { @@ -38,7 +35,8 @@ pub struct Button { text: Text, - action_id: String, + #[serde(skip_serializing_if = "Option::is_none")] + action_id: Option, #[serde(skip_serializing_if = "Option::is_none")] url: Option, @@ -56,308 +54,456 @@ pub struct Button { accessibility_label: Option, } -impl Default for Button { - fn default() -> Self { - Self { - kind: "button", - text: plain_text!(""), - action_id: "".into(), - url: None, - value: None, - style: None, - confirm: None, - accessibility_label: None, - } +impl Button { + /// Construct a [`ButtonBuilder`]. + pub fn builder() -> ButtonBuilder { + ButtonBuilder::default() } } -impl Button { - /// Constructs a Button element. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::Button; - /// use serde_json::json; +/// Builder for [`Button`] object. +#[derive(Debug, Default)] +pub struct ButtonBuilder { + text: Option, + action_id: Option, + url: Option, + value: Option, + style: Option<&'static str>, + confirm: Option, + accessibility_label: Option, +} + +impl ButtonBuilder { + /// Set text field. /// - /// let button = Button::new(); + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true - /// }, - /// "action_id": "" + /// "text": "Click Me" + /// } /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn new() -> Self { - Self::default() + pub fn text(self, text: impl Into) -> Self { + self.set_text(Some(text.into())) } - /// Sets text field. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::{Button, Text}; - /// use serde_json::json; + /// Set text field. /// - /// let button = Button::new().set_text(Text::plain("Click Me")); + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .set_text(Some("Click Me".into())) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "Click Me", - /// "emoji": true - /// }, - /// "action_id": "" + /// "text": "Click Me" + /// } /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_text(self, text: Text) -> Self { + pub fn set_text(self, text: Option) -> Self { Self { text, ..self } } - /// Sets action_id field. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::Button; - /// use serde_json::json; + /// Set action_id field. /// - /// let button = Button::new().set_action_id("click_me_123"); + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .action_id("click_me_123") + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "Click Me" /// }, /// "action_id": "click_me_123" /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_action_id>(self, action_id: T) -> Self { - Self { - action_id: action_id.into(), - ..self - } + pub fn action_id(self, action_id: impl Into) -> Self { + self.set_action_id(Some(action_id.into())) } - /// Sets url field. + /// Set action_id field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::Button; - /// use serde_json::json; + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .set_action_id(Some("click_me_123".into())) + /// .build(); /// - /// let button = Button::new().set_url("https://google.com"); + /// let expected = serde_json::json!({ + /// "type": "button", + /// "text": { + /// "type": "plain_text", + /// "text": "Click Me" + /// }, + /// "action_id": "click_me_123" + /// }); + /// + /// let json = serde_json::to_value(button).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_action_id(self, action_id: Option) -> Self { + Self { action_id, ..self } + } + + /// Set url field. /// - /// let expected = json!({ + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .url("https://google.com") + /// .build(); + /// + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "Click Me" /// }, - /// "action_id": "", /// "url": "https://google.com" /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_url>(self, url: T) -> Self { - Self { - url: Some(url.into()), - ..self - } + pub fn url(self, url: impl Into) -> Self { + self.set_url(Some(url.into())) } - /// Sets value field. + /// Set url field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::Button; - /// use serde_json::json; + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .set_url(Some("https://google.com".into())) + /// .build(); /// - /// let button = Button::new().set_value("value-0"); + /// let expected = serde_json::json!({ + /// "type": "button", + /// "text": { + /// "type": "plain_text", + /// "text": "Click Me" + /// }, + /// "url": "https://google.com" + /// }); /// - /// let expected = json!({ + /// let json = serde_json::to_value(button).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_url(self, url: Option) -> Self { + Self { url, ..self } + } + + /// Set value field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .value("value-0") + /// .build(); + /// + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "Click Me" /// }, - /// "action_id": "", /// "value": "value-0" /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_value>(self, value: T) -> Self { - Self { - value: Some(value.into()), - ..self - } + pub fn value(self, value: impl Into) -> Self { + self.set_value(Some(value.into())) } - /// Sets primary to style field. + /// Set value field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::Button; - /// use serde_json::json; + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .set_value(Some("value-0".into())) + /// .build(); /// - /// let button = Button::new().set_primary(); + /// let expected = serde_json::json!({ + /// "type": "button", + /// "text": { + /// "type": "plain_text", + /// "text": "Click Me" + /// }, + /// "value": "value-0" + /// }); + /// + /// let json = serde_json::to_value(button).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_value(self, value: Option) -> Self { + Self { value, ..self } + } + + /// Set primary to style field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .primary() + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "Click Me" /// }, - /// "action_id": "", /// "style": "primary" /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_primary(self) -> Self { + pub fn primary(self) -> Self { Self { style: Some("primary"), ..self } } - /// Sets danger to style field. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::Button; - /// use serde_json::json; + /// Set danger to style field. /// - /// let button = Button::new().set_danger(); + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .danger() + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "Click Me" /// }, - /// "action_id": "", /// "style": "danger" /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_danger(self) -> Self { + pub fn danger(self) -> Self { Self { style: Some("danger"), ..self } } - /// Sets confirm field with ConfirmationDialog object. + /// Set confirm field with ConfirmationDialog object. + /// + /// ``` + /// # use slack_messaging::blocks::elements::{Button, ConfirmationDialog}; + /// let button = Button::builder() + /// .text("Click Me") + /// .confirm( + /// ConfirmationDialog::builder() + /// .title("Are you sure?") + /// .text("Wouldn't you prefer a good game of _chess_?") + /// .confirm("Do it") + /// .deny("Stop, I've changed my mind!") + /// .build() + /// ) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "type": "button", + /// "text": { + /// "type": "plain_text", + /// "text": "Click Me" + /// }, + /// "confirm": { + /// "title": { + /// "type": "plain_text", + /// "text": "Are you sure?" + /// }, + /// "text": { + /// "type": "plain_text", + /// "text": "Wouldn't you prefer a good game of _chess_?" + /// }, + /// "confirm": { + /// "type": "plain_text", + /// "text": "Do it" + /// }, + /// "deny": { + /// "type": "plain_text", + /// "text": "Stop, I've changed my mind!" + /// } + /// } + /// }); + /// + /// let json = serde_json::to_value(button).unwrap(); /// - /// ```ignore - /// use slack_messaging::blocks::elements::{Button, ConfirmationDialog}; - /// use serde_json::json; + /// assert_eq!(json, expected); + /// ``` + pub fn confirm(self, confirm: ConfirmationDialog) -> Self { + self.set_confirm(Some(confirm)) + } + + /// Set confirm field with ConfirmationDialog object. /// - /// let button = Button::new() + /// ``` + /// # use slack_messaging::blocks::elements::{Button, ConfirmationDialog}; + /// let button = Button::builder() + /// .text("Click Me") /// .set_confirm( - /// ConfirmationDialog::new() - /// .set_title("Are you sure?") - /// .set_text("Wouldn't you prefer a good game of _chess_?") - /// .set_confirm("Do it") - /// .set_deny("Stop, I've changed my mind!") - /// ); - /// - /// let expected = json!({ + /// Some(ConfirmationDialog::builder() + /// .title("Are you sure?") + /// .text("Wouldn't you prefer a good game of _chess_?") + /// .confirm("Do it") + /// .deny("Stop, I've changed my mind!") + /// .build()) + /// ) + /// .build(); + /// + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "Click Me" /// }, - /// "action_id": "", /// "confirm": { /// "title": { /// "type": "plain_text", - /// "text": "Are you sure?", - /// "emoji": true + /// "text": "Are you sure?" /// }, /// "text": { /// "type": "plain_text", - /// "text": "Wouldn't you prefer a good game of _chess_?", - /// "emoji": true + /// "text": "Wouldn't you prefer a good game of _chess_?" /// }, /// "confirm": { /// "type": "plain_text", - /// "text": "Do it", - /// "emoji": true + /// "text": "Do it" /// }, /// "deny": { /// "type": "plain_text", - /// "text": "Stop, I've changed my mind!", - /// "emoji": true + /// "text": "Stop, I've changed my mind!" /// } /// } /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_confirm(self, confirm: ConfirmationDialog) -> Self { - Self { - confirm: Some(confirm), - ..self - } + pub fn set_confirm(self, confirm: Option) -> Self { + Self { confirm, ..self } } - /// Sets accessibility_label field. + /// Set accessibility_label field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::Button; - /// use serde_json::json; + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .accessibility_label("Click Me") + /// .build(); /// - /// let button = Button::new().set_accessibility_label("Click Me"); + /// let expected = serde_json::json!({ + /// "type": "button", + /// "text": { + /// "type": "plain_text", + /// "text": "Click Me" + /// }, + /// "accessibility_label": "Click Me" + /// }); /// - /// let expected = json!({ + /// let json = serde_json::to_value(button).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn accessibility_label(self, label: impl Into) -> Self { + self.set_accessibility_label(Some(label.into())) + } + + /// Set accessibility_label field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Button; + /// let button = Button::builder() + /// .text("Click Me") + /// .set_accessibility_label(Some("Click Me".into())) + /// .build(); + /// + /// let expected = serde_json::json!({ /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "Click Me" /// }, - /// "action_id": "", /// "accessibility_label": "Click Me" /// }); /// - /// let button_json = serde_json::to_value(button).unwrap(); + /// let json = serde_json::to_value(button).unwrap(); /// - /// assert_eq!(button_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_accessibility_label>(self, label: T) -> Self { + pub fn set_accessibility_label(self, label: Option) -> Self { Self { - accessibility_label: Some(label.into()), + accessibility_label: label, ..self } } + + /// Build a [`Button`] object. This method will panic if the `text` is not set. + pub fn build(self) -> Button { + Button { + kind: "button", + text: Text::builder() + .plain_text(self.text.expect("text must be set to ButtonBuilder")) + .build(), + action_id: self.action_id, + url: self.url, + value: self.value, + style: self.style, + confirm: self.confirm, + accessibility_label: self.accessibility_label, + } + } } diff --git a/src/blocks/elements/confirmation_dialog.rs b/src/blocks/elements/confirmation_dialog.rs index e258fa6..29bd2da 100644 --- a/src/blocks/elements/confirmation_dialog.rs +++ b/src/blocks/elements/confirmation_dialog.rs @@ -1,5 +1,4 @@ use super::Text; -use crate::plain_text; use serde::Serialize; /// [Confirmation dialog object](https://api.slack.com/reference/block-kit/composition-objects#confirm) @@ -7,42 +6,37 @@ use serde::Serialize; /// /// # Example /// -/// ```ignore -/// use slack_messaging::blocks::elements::ConfirmationDialog; -/// use serde_json::json; -/// -/// let confirm = ConfirmationDialog::new() -/// .set_title("Are you sure?") -/// .set_text("Wouldn't you prefer a good game of _chess_?") -/// .set_confirm("Do it") -/// .set_deny("Stop, I've changed my mind!"); +/// ``` +/// # use slack_messaging::blocks::elements::ConfirmationDialog; +/// let dialog = ConfirmationDialog::builder() +/// .title("Are you sure?") +/// .text("Wouldn't you prefer a good game of _chess_?") +/// .confirm("Do it") +/// .deny("Stop, I've changed my mind!") +/// .build(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "title": { /// "type": "plain_text", -/// "text": "Are you sure?", -/// "emoji": true +/// "text": "Are you sure?" /// }, /// "text": { /// "type": "plain_text", -/// "text": "Wouldn't you prefer a good game of _chess_?", -/// "emoji": true +/// "text": "Wouldn't you prefer a good game of _chess_?" /// }, /// "confirm": { /// "type": "plain_text", -/// "text": "Do it", -/// "emoji": true +/// "text": "Do it" /// }, /// "deny": { /// "type": "plain_text", -/// "text": "Stop, I've changed my mind!", -/// "emoji": true +/// "text": "Stop, I've changed my mind!" /// } /// }); /// -/// let confirm_json = serde_json::to_value(confirm).unwrap(); +/// let json = serde_json::to_value(dialog).unwrap(); /// -/// assert_eq!(confirm_json, expected); +/// assert_eq!(json, expected); /// ``` #[derive(Debug, Clone, Serialize)] pub struct ConfirmationDialog { @@ -58,142 +52,281 @@ pub struct ConfirmationDialog { style: Option<&'static str>, } -impl Default for ConfirmationDialog { - fn default() -> Self { - Self { - title: plain_text!(""), - text: plain_text!(""), - confirm: plain_text!(""), - deny: plain_text!(""), - style: None, - } +impl ConfirmationDialog { + /// Construct a [`ConfirmationDialogBuilder`]. + pub fn builder() -> ConfirmationDialogBuilder { + ConfirmationDialogBuilder::default() } } -impl ConfirmationDialog { - /// Constructs a Confirmation dialog object with empty values. +/// Builder for [`ConfirmationDialog`] object. +#[derive(Debug, Default)] +pub struct ConfirmationDialogBuilder { + title: Option, + text: Option, + confirm: Option, + deny: Option, + style: Option<&'static str>, +} + +impl ConfirmationDialogBuilder { + /// Set title field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::ConfirmationDialog; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; /// - /// let confirm = ConfirmationDialog::new(); + /// let dialog = ConfirmationDialog::builder() + /// .title("Are you sure?") + /// .text("") + /// .confirm("") + /// .deny("") + /// .build(); /// - /// let confirm_json = serde_json::to_value(confirm).unwrap(); + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("Are you sure?".into()); /// - /// assert_eq!(confirm_json["title"]["text"], Value::String("".into())); - /// assert_eq!(confirm_json["text"]["text"], Value::String("".into())); - /// assert_eq!(confirm_json["confirm"]["text"], Value::String("".into())); - /// assert_eq!(confirm_json["deny"]["text"], Value::String("".into())); - /// assert_eq!(confirm_json["style"], Value::Null); + /// assert_eq!(json["title"]["text"], expected); /// ``` - pub fn new() -> Self { - Self::default() + pub fn title(self, title: impl Into) -> Self { + self.set_title(Some(title.into())) } - /// Sets title field with plain_text object. + /// Set title field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::ConfirmationDialog; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; /// - /// let confirm = ConfirmationDialog::new() - /// .set_title("Are you sure?"); + /// let dialog = ConfirmationDialog::builder() + /// .set_title(Some("Are you sure?".into())) + /// .text("") + /// .confirm("") + /// .deny("") + /// .build(); /// - /// let confirm_json = serde_json::to_value(confirm).unwrap(); + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("Are you sure?".into()); /// - /// assert_eq!(confirm_json["title"]["text"], Value::String("Are you sure?".into())); + /// assert_eq!(json["title"]["text"], expected); /// ``` - pub fn set_title(self, title: Text) -> Self { + pub fn set_title(self, title: Option) -> Self { Self { title, ..self } } - /// Sets text field with plain_text object. + /// Set text field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::ConfirmationDialog; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; + /// + /// let dialog = ConfirmationDialog::builder() + /// .title("") + /// .text("Wouldn't you prefer a good game of _chess_?") + /// .confirm("") + /// .deny("") + /// .build(); /// - /// let confirm = ConfirmationDialog::new() - /// .set_text("Wouldn't you prefer a good game of _chess_?"); + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("Wouldn't you prefer a good game of _chess_?".into()); /// - /// let confirm_json = serde_json::to_value(confirm).unwrap(); + /// assert_eq!(json["text"]["text"], expected); + /// ``` + pub fn text(self, text: impl Into) -> Self { + self.set_text(Some(text.into())) + } + + /// Set text field. /// - /// assert_eq!(confirm_json["text"]["text"], Value::String("Wouldn't you prefer a good game of _chess_?".into())); /// ``` - pub fn set_text(self, text: Text) -> Self { + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; + /// + /// let dialog = ConfirmationDialog::builder() + /// .title("") + /// .set_text(Some("Wouldn't you prefer a good game of _chess_?".into())) + /// .confirm("") + /// .deny("") + /// .build(); + /// + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("Wouldn't you prefer a good game of _chess_?".into()); + /// + /// assert_eq!(json["text"]["text"], expected); + /// ``` + pub fn set_text(self, text: Option) -> Self { Self { text, ..self } } - /// Sets confirm field with plain_text object. + /// Set confirm field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::ConfirmationDialog; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; /// - /// let confirm = ConfirmationDialog::new() - /// .set_confirm("Do it"); + /// let dialog = ConfirmationDialog::builder() + /// .title("") + /// .text("") + /// .confirm("Do it") + /// .deny("") + /// .build(); /// - /// let confirm_json = serde_json::to_value(confirm).unwrap(); + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("Do it".into()); /// - /// assert_eq!(confirm_json["confirm"]["text"], Value::String("Do it".into())); + /// assert_eq!(json["confirm"]["text"], expected); /// ``` - pub fn set_confirm(self, confirm: Text) -> Self { + pub fn confirm(self, confirm: impl Into) -> Self { + self.set_confirm(Some(confirm.into())) + } + + /// Set confirm field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; + /// + /// let dialog = ConfirmationDialog::builder() + /// .title("") + /// .text("") + /// .set_confirm(Some("Do it".into())) + /// .deny("") + /// .build(); + /// + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("Do it".into()); + /// + /// assert_eq!(json["confirm"]["text"], expected); + /// ``` + pub fn set_confirm(self, confirm: Option) -> Self { Self { confirm, ..self } } - /// Sets deny field with plain_text object. + /// Set deny field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::ConfirmationDialog; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; /// - /// let confirm = ConfirmationDialog::new() - /// .set_deny("Stop, I've changed my mind!"); + /// let dialog = ConfirmationDialog::builder() + /// .title("") + /// .text("") + /// .confirm("") + /// .deny("Stop, I've changed my mind!") + /// .build(); /// - /// let confirm_json = serde_json::to_value(confirm).unwrap(); + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("Stop, I've changed my mind!".into()); /// - /// assert_eq!(confirm_json["deny"]["text"], Value::String("Stop, I've changed my mind!".into())); + /// assert_eq!(json["deny"]["text"], expected); /// ``` - pub fn set_deny(self, deny: Text) -> Self { + pub fn deny(self, deny: impl Into) -> Self { + self.set_deny(Some(deny.into())) + } + + /// Set deny field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; + /// + /// let dialog = ConfirmationDialog::builder() + /// .title("") + /// .text("") + /// .confirm("") + /// .set_deny(Some("Stop, I've changed my mind!".into())) + /// .build(); + /// + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("Stop, I've changed my mind!".into()); + /// + /// assert_eq!(json["deny"]["text"], expected); + /// ``` + pub fn set_deny(self, deny: Option) -> Self { Self { deny, ..self } } - /// Sets style field as "primary". + /// Set "primary" to style field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::ConfirmationDialog; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; /// - /// let confirm = ConfirmationDialog::new().set_primary(); + /// let dialog = ConfirmationDialog::builder() + /// .title("") + /// .text("") + /// .confirm("") + /// .deny("") + /// .primary() + /// .build(); /// - /// let confirm_json = serde_json::to_value(confirm).unwrap(); + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("primary".into()); /// - /// assert_eq!(confirm_json["style"], Value::String("primary".into())); + /// assert_eq!(json["style"], expected); /// ``` - pub fn set_primary(self) -> Self { + pub fn primary(self) -> Self { Self { style: Some("primary"), ..self } } - /// Sets style field as "danger". + /// Set "danger" to style field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::ConfirmationDialog; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::blocks::elements::ConfirmationDialog; + /// use serde_json::Value; /// - /// let confirm = ConfirmationDialog::new().set_danger(); + /// let dialog = ConfirmationDialog::builder() + /// .title("") + /// .text("") + /// .confirm("") + /// .deny("") + /// .danger() + /// .build(); /// - /// let confirm_json = serde_json::to_value(confirm).unwrap(); + /// let json = serde_json::to_value(dialog).unwrap(); + /// let expected = Value::String("danger".into()); /// - /// assert_eq!(confirm_json["style"], Value::String("danger".into())); + /// assert_eq!(json["style"], expected); /// ``` - pub fn set_danger(self) -> Self { + pub fn danger(self) -> Self { Self { style: Some("danger"), ..self } } + + /// Build a [`ConfirmationDialog`] object. This method will panic if any of + /// the `title`, `text`, `confirm` and `deny` is not set. + pub fn build(self) -> ConfirmationDialog { + ConfirmationDialog { + title: Text::builder() + .plain_text( + self.title + .expect("title must be set to ConfirmationDialogBuilder"), + ) + .build(), + text: Text::builder() + .plain_text( + self.text + .expect("text must be set to ConfirmationDialogBuilder"), + ) + .build(), + confirm: Text::builder() + .plain_text( + self.confirm + .expect("confirm must be set to ConfirmationDialogBuilder"), + ) + .build(), + deny: Text::builder() + .plain_text( + self.deny + .expect("deny must be set to ConfirmationDialogBuilder"), + ) + .build(), + style: self.style, + } + } } diff --git a/src/blocks/elements/dispatch_action_configuration.rs b/src/blocks/elements/dispatch_action_configuration.rs index e0d5ece..4849534 100644 --- a/src/blocks/elements/dispatch_action_configuration.rs +++ b/src/blocks/elements/dispatch_action_configuration.rs @@ -16,75 +16,67 @@ pub enum TriggerAction { /// /// # Example /// -/// ```ignore -/// use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; -/// use serde_json::json; -/// -/// let config = DispatchActionConfiguration::new() -/// .push_trigger_action(TriggerAction::OnEnterPressed) -/// .push_trigger_action(TriggerAction::OnCharacterEntered); +/// ``` +/// # use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; +/// let config = DispatchActionConfiguration::builder() +/// .trigger_action(TriggerAction::OnEnterPressed) +/// .trigger_action(TriggerAction::OnCharacterEntered) +/// .build(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "trigger_actions_on": [ /// "on_enter_pressed", /// "on_character_entered" /// ] /// }); /// -/// let config_json = serde_json::to_value(config).unwrap(); +/// let json = serde_json::to_value(config).unwrap(); /// -/// assert_eq!(config_json, expected); +/// assert_eq!(json, expected); /// ``` -#[derive(Debug, Default, Clone, Serialize)] +#[derive(Debug, Clone, Serialize)] pub struct DispatchActionConfiguration { + #[serde(skip_serializing_if = "Vec::is_empty")] trigger_actions_on: Vec, } impl DispatchActionConfiguration { - /// Constructs a Dispatch action configuration. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::DispatchActionConfiguration; - /// use serde_json::json; - /// - /// let config = DispatchActionConfiguration::new(); - /// - /// let expected = json!({ - /// "trigger_actions_on": [] - /// }); - /// - /// let config_json = serde_json::to_value(config).unwrap(); - /// - /// assert_eq!(config_json, expected); - /// ``` - pub fn new() -> Self { - Self::default() + /// Construct a [`DispatchActionConfigurationBuilder`]. + pub fn builder() -> DispatchActionConfigurationBuilder { + DispatchActionConfigurationBuilder::default() } +} - /// Sets trigger_actions_on field directly. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; - /// use serde_json::json; +/// Builder for [`DispatchActionConfiguration`] object. +#[derive(Debug, Default)] +pub struct DispatchActionConfigurationBuilder { + trigger_actions_on: Vec, +} + +impl DispatchActionConfigurationBuilder { + /// Set trigger_actions_on field. /// - /// let config = DispatchActionConfiguration::new() + /// ``` + /// # use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; + /// let config = DispatchActionConfiguration::builder() /// .set_trigger_actions( /// vec![ /// TriggerAction::OnEnterPressed, /// TriggerAction::OnCharacterEntered, /// ] - /// ); + /// ) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "trigger_actions_on": [ /// "on_enter_pressed", /// "on_character_entered" /// ] /// }); /// - /// let config_json = serde_json::to_value(config).unwrap(); + /// let json = serde_json::to_value(config).unwrap(); /// - /// assert_eq!(config_json, expected); + /// assert_eq!(json, expected); /// ``` pub fn set_trigger_actions(self, actions: Vec) -> Self { Self { @@ -92,30 +84,36 @@ impl DispatchActionConfiguration { } } - /// Adds trigger_action to trigger_actions_on field. + /// Add trigger_action to trigger_actions_on field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; - /// use serde_json::json; - /// - /// let config = DispatchActionConfiguration::new() - /// .push_trigger_action(TriggerAction::OnEnterPressed); + /// ``` + /// # use slack_messaging::blocks::elements::{DispatchActionConfiguration, TriggerAction}; + /// let config = DispatchActionConfiguration::builder() + /// .trigger_action(TriggerAction::OnEnterPressed) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "trigger_actions_on": [ /// "on_enter_pressed" /// ] /// }); /// - /// let config_json = serde_json::to_value(config).unwrap(); + /// let json = serde_json::to_value(config).unwrap(); /// - /// assert_eq!(config_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn push_trigger_action(self, action: TriggerAction) -> Self { + pub fn trigger_action(self, action: TriggerAction) -> Self { let Self { mut trigger_actions_on, } = self; trigger_actions_on.push(action); Self { trigger_actions_on } } + + /// Build a [`DispatchActionConfiguration`] object. + pub fn build(self) -> DispatchActionConfiguration { + DispatchActionConfiguration { + trigger_actions_on: self.trigger_actions_on, + } + } } diff --git a/src/blocks/elements/filter.rs b/src/blocks/elements/filter.rs index eeac9f0..e4b33c4 100644 --- a/src/blocks/elements/filter.rs +++ b/src/blocks/elements/filter.rs @@ -15,16 +15,15 @@ pub enum Conversation { /// /// # Example /// -/// ```ignore -/// use slack_messaging::blocks::elements::{Filter, Conversation}; -/// use serde_json::json; -/// -/// let filter = Filter::new() +/// ``` +/// # use slack_messaging::blocks::elements::{Filter, Conversation}; +/// let filter = Filter::builder() /// .include(Conversation::Public) /// .include(Conversation::Mpim) -/// .exclude_bot_users(); +/// .exclude_bot_users(true) +/// .build(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "include": [ /// "public", /// "mpim" @@ -32,11 +31,11 @@ pub enum Conversation { /// "exclude_bot_users": true /// }); /// -/// let filter_json = serde_json::to_value(filter).unwrap(); +/// let json = serde_json::to_value(filter).unwrap(); /// -/// assert_eq!(filter_json, expected); +/// assert_eq!(json, expected); /// ``` -#[derive(Debug, Default, Clone, Serialize)] +#[derive(Debug, Clone, Serialize)] pub struct Filter { #[serde(skip_serializing_if = "Vec::is_empty")] include: Vec, @@ -49,170 +48,167 @@ pub struct Filter { } impl Filter { - /// Constructs a Filter object. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::Filter; - /// use serde_json::json; - /// - /// let filter = Filter::new(); - /// - /// let expected = json!({}); - /// - /// let filter_json = serde_json::to_value(filter).unwrap(); - /// - /// assert_eq!(filter_json, expected); - /// ``` - pub fn new() -> Self { - Self::default() + /// Construct a [`FilterBuilder`]. + pub fn builder() -> FilterBuilder { + FilterBuilder::default() } +} - /// Sets include field directly. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::{Filter, Conversation}; - /// use serde_json::json; +/// Builder for [`Filter`] object. +#[derive(Debug, Default)] +pub struct FilterBuilder { + include: Vec, + exclude_external_shared_channels: Option, + exclude_bot_users: Option, +} + +impl FilterBuilder { + /// Set include field. /// - /// let filter = Filter::new() + /// ``` + /// # use slack_messaging::blocks::elements::{Filter, Conversation}; + /// let filter = Filter::builder() /// .set_include( /// vec![ /// Conversation::Im, /// Conversation::Private, /// ] - /// ); + /// ) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "include": [ /// "im", /// "private" /// ] /// }); /// - /// let filter_json = serde_json::to_value(filter).unwrap(); + /// let json = serde_json::to_value(filter).unwrap(); /// - /// assert_eq!(filter_json, expected); + /// assert_eq!(json, expected); /// ``` pub fn set_include(self, include: Vec) -> Self { Self { include, ..self } } - /// Adds conversation to include field. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::{Filter, Conversation}; - /// use serde_json::json; + /// Add conversation to include field. /// - /// let filter = Filter::new() - /// .push_include(Conversation::Mpim); + /// ``` + /// # use slack_messaging::blocks::elements::{Filter, Conversation}; + /// let filter = Filter::builder() + /// .include(Conversation::Mpim) + /// .include(Conversation::Public) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "include": [ - /// "mpim" + /// "mpim", + /// "public" /// ] /// }); /// - /// let filter_json = serde_json::to_value(filter).unwrap(); + /// let json = serde_json::to_value(filter).unwrap(); /// - /// assert_eq!(filter_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn push_include(self, conversation: Conversation) -> Self { + pub fn include(self, conversation: Conversation) -> Self { let Self { mut include, .. } = self; include.push(conversation); Self { include, ..self } } - /// Alias for `push_include` method - pub fn include(self, conversation: Conversation) -> Self { - self.push_include(conversation) - } - - /// Sets exclude_external_shared_channels field. + /// Set exclude_external_shared_channels field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::{Filter, Conversation}; - /// use serde_json::json; - /// - /// let filter = Filter::new() - /// .set_exclude_external_shared_channels(true); + /// ``` + /// # use slack_messaging::blocks::elements::{Filter, Conversation}; + /// let filter = Filter::builder() + /// .set_exclude_external_shared_channels(Some(true)) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "exclude_external_shared_channels": true /// }); /// - /// let filter_json = serde_json::to_value(filter).unwrap(); + /// let json = serde_json::to_value(filter).unwrap(); /// - /// assert_eq!(filter_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_exclude_external_shared_channels(self, value: bool) -> Self { + pub fn set_exclude_external_shared_channels(self, value: Option) -> Self { Self { - exclude_external_shared_channels: Some(value), + exclude_external_shared_channels: value, ..self } } - /// Sets true to exclude_external_shared_channels field. + /// Set exclude_external_shared_channels field. /// - /// ```ignore + /// ``` /// use slack_messaging::blocks::elements::{Filter, Conversation}; - /// use serde_json::json; - /// - /// let filter = Filter::new() - /// .exclude_external_shared_channels(); + /// let filter = Filter::builder() + /// .exclude_external_shared_channels(true) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "exclude_external_shared_channels": true /// }); /// - /// let filter_json = serde_json::to_value(filter).unwrap(); + /// let json = serde_json::to_value(filter).unwrap(); /// - /// assert_eq!(filter_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn exclude_external_shared_channels(self) -> Self { - self.set_exclude_external_shared_channels(true) + pub fn exclude_external_shared_channels(self, value: bool) -> Self { + self.set_exclude_external_shared_channels(Some(value)) } - /// Sets exclude_bot_users field. + /// Set exclude_bot_users field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::{Filter, Conversation}; - /// use serde_json::json; - /// - /// let filter = Filter::new() - /// .set_exclude_bot_users(true); + /// ``` + /// # use slack_messaging::blocks::elements::{Filter, Conversation}; + /// let filter = Filter::builder() + /// .set_exclude_bot_users(Some(true)) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "exclude_bot_users": true /// }); /// - /// let filter_json = serde_json::to_value(filter).unwrap(); + /// let json = serde_json::to_value(filter).unwrap(); /// - /// assert_eq!(filter_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_exclude_bot_users(self, value: bool) -> Self { + pub fn set_exclude_bot_users(self, value: Option) -> Self { Self { - exclude_bot_users: Some(value), + exclude_bot_users: value, ..self } } - /// Sets true to exclude_bot_users field. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::{Filter, Conversation}; - /// use serde_json::json; + /// Set exclude_bot_users field. /// - /// let filter = Filter::new() - /// .exclude_bot_users(); + /// ``` + /// # use slack_messaging::blocks::elements::{Filter, Conversation}; + /// let filter = Filter::builder() + /// .exclude_bot_users(true) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "exclude_bot_users": true /// }); /// - /// let filter_json = serde_json::to_value(filter).unwrap(); + /// let json = serde_json::to_value(filter).unwrap(); /// - /// assert_eq!(filter_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn exclude_bot_users(self) -> Self { - self.set_exclude_bot_users(true) + pub fn exclude_bot_users(self, value: bool) -> Self { + self.set_exclude_bot_users(Some(value)) + } + + /// Build a [`Filter`] object. + pub fn build(self) -> Filter { + Filter { + include: self.include, + exclude_external_shared_channels: self.exclude_external_shared_channels, + exclude_bot_users: self.exclude_bot_users, + } } } diff --git a/src/blocks/elements/input_parameter.rs b/src/blocks/elements/input_parameter.rs new file mode 100644 index 0000000..66582ea --- /dev/null +++ b/src/blocks/elements/input_parameter.rs @@ -0,0 +1,143 @@ +use serde::Serialize; +use serde_json::Value; + +/// [Input parameter object](https://api.slack.com/reference/block-kit/composition-objects#input_parameter) representation. +/// +/// # Example +/// +/// ``` +/// # use slack_messaging::blocks::elements::InputParameter; +/// let param = InputParameter::builder() +/// .name("input_parameter_a") +/// .value("Value for input param A") +/// .build(); +/// +/// let expected = serde_json::json!({ +/// "name": "input_parameter_a", +/// "value": "Value for input param A" +/// }); +/// +/// let json = serde_json::to_value(param).unwrap(); +/// +/// assert_eq!(json, expected); +/// ``` +#[derive(Debug, Clone, Serialize)] +pub struct InputParameter { + name: String, + value: Value, +} + +impl InputParameter { + /// Construct a [`InputParameterBuilder`]. + pub fn builder() -> InputParameterBuilder { + InputParameterBuilder::default() + } +} + +/// Builder for [`InputParameter`] object. +#[derive(Debug, Default)] +pub struct InputParameterBuilder { + name: Option, + value: Option, +} + +impl InputParameterBuilder { + /// Set name field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::InputParameter; + /// let param = InputParameter::builder() + /// .set_name(Some("input_parameter_a".into())) + /// .value("") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "name": "input_parameter_a", + /// "value": "" + /// }); + /// + /// let json = serde_json::to_value(param).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_name(self, name: Option) -> Self { + Self { name, ..self } + } + + /// Set name field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::InputParameter; + /// let param = InputParameter::builder() + /// .name("input_parameter_a") + /// .value("") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "name": "input_parameter_a", + /// "value": "" + /// }); + /// + /// let json = serde_json::to_value(param).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn name(self, name: impl Into) -> Self { + self.set_name(Some(name.into())) + } + + /// Set value field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::InputParameter; + /// use serde_json::Value; + /// + /// let param = InputParameter::builder() + /// .name("") + /// .set_value(Some(Value::String("Value for input param A".into()))) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "name": "", + /// "value": "Value for input param A" + /// }); + /// + /// let json = serde_json::to_value(param).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_value(self, value: Option) -> Self { + Self { value, ..self } + } + + /// Set value field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::InputParameter; + /// let param = InputParameter::builder() + /// .name("") + /// .value("Value for input param A") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "name": "", + /// "value": "Value for input param A" + /// }); + /// + /// let json = serde_json::to_value(param).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn value(self, value: impl Into) -> Self { + self.set_value(Some(value.into())) + } + + /// Build a [`InputParameter`] object. This method will panic if both `name` and `value` are + /// not set. + pub fn build(self) -> InputParameter { + InputParameter { + name: self.name.expect("name must be set to InputParameterBuilder"), + value: self.value.expect("value must be set to InputParameterBuilder"), + } + } +} diff --git a/src/blocks/elements/mod.rs b/src/blocks/elements/mod.rs index c911a5e..7285138 100644 --- a/src/blocks/elements/mod.rs +++ b/src/blocks/elements/mod.rs @@ -1,20 +1,21 @@ -mod button; +pub mod button; mod checkbox_group; -mod confirmation_dialog; +pub mod confirmation_dialog; mod datepicker; mod datetimepicker; -mod dispatch_action_configuration; +pub mod dispatch_action_configuration; mod email_input; -mod filter; +pub mod filter; mod image; +pub mod input_parameter; mod multi_select_conversations; mod multi_select_externals; mod multi_select_public_channels; mod multi_select_static_options; mod multi_select_users; mod number_input; -mod opt; -mod opt_group; +pub mod opt; +pub mod opt_group; mod overflow_menu; mod plain_text_input; mod radio_button_group; @@ -23,9 +24,12 @@ mod select_externals; mod select_public_channels; mod select_static_options; mod select_users; -mod text; +pub mod slack_file; +pub mod text; mod timepicker; +pub mod trigger; mod url_input; +pub mod workflow; pub use button::Button; pub use checkbox_group::CheckboxGroup; @@ -36,6 +40,7 @@ pub use dispatch_action_configuration::{DispatchActionConfiguration, TriggerActi pub use email_input::EmailInput; pub use filter::{Conversation, Filter}; pub use image::Image; +pub use input_parameter::InputParameter; pub use multi_select_conversations::MultiSelectConversations; pub use multi_select_externals::MultiSelectExternals; pub use multi_select_public_channels::MultiSelectPublicChannels; @@ -52,6 +57,9 @@ pub use select_externals::SelectExternals; pub use select_public_channels::SelectPublicChannels; pub use select_static_options::SelectStaticOptions; pub use select_users::SelectUsers; +pub use slack_file::SlackFile; pub use text::Text; pub use timepicker::TimePicker; +pub use trigger::Trigger; pub use url_input::UrlInput; +pub use workflow::Workflow; diff --git a/src/blocks/elements/opt.rs b/src/blocks/elements/opt.rs index 0d1fb8f..73acb8b 100644 --- a/src/blocks/elements/opt.rs +++ b/src/blocks/elements/opt.rs @@ -1,5 +1,4 @@ use super::Text; -use crate::plain_text; use serde::Serialize; /// [Option object](https://api.slack.com/reference/block-kit/composition-objects#option) @@ -7,26 +6,24 @@ use serde::Serialize; /// /// # Example /// -/// ```ignore -/// use slack_messaging::blocks::elements::{Opt, Text}; -/// use serde_json::json; -/// -/// let option = Opt::new() -/// .set_text(Text::plain("Maru")) -/// .set_value("maru"); +/// ``` +/// # use slack_messaging::blocks::elements::{Opt, Text}; +/// let option = Opt::builder() +/// .text("Maru") +/// .value("maru") +/// .build(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "text": { /// "type": "plain_text", -/// "text": "Maru", -/// "emoji": true +/// "text": "Maru" /// }, /// "value": "maru" /// }); /// -/// let option_json = serde_json::to_value(option).unwrap(); +/// let json = serde_json::to_value(option).unwrap(); /// -/// assert_eq!(option_json, expected); +/// assert_eq!(json, expected); /// ``` #[derive(Debug, Clone, Serialize)] pub struct Opt { @@ -41,139 +38,266 @@ pub struct Opt { url: Option, } -impl Default for Opt { - fn default() -> Self { - Self { - text: plain_text!(""), - value: "".into(), - description: None, - url: None, - } +impl Opt { + /// Construct a [`OptBuilder`]. + pub fn builder() -> OptBuilder { + OptBuilder::default() } } -impl Opt { - /// Constructs a Option object with empty values. +/// Builder for [`Opt`] object. +#[derive(Debug, Default)] +pub struct OptBuilder { + text: Option, + value: Option, + description: Option, + url: Option +} + +impl OptBuilder { + /// Set text field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::Opt; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::plain_text; + /// # use slack_messaging::blocks::elements::Opt; + /// let text = plain_text!("This is a plain text."); + /// let option = Opt::builder() + /// .set_text(Some(text)) + /// .value("") + /// .build(); /// - /// let option = Opt::new(); + /// let expected = serde_json::json!({ + /// "text": { + /// "type": "plain_text", + /// "text": "This is a plain text." + /// }, + /// "value": "" + /// }); /// - /// let option_json = serde_json::to_value(option).unwrap(); + /// let json = serde_json::to_value(option).unwrap(); /// - /// assert_eq!(option_json["text"]["text"], Value::String("".into())); - /// assert_eq!(option_json["value"], Value::String("".into())); - /// assert_eq!(option_json["description"], Value::Null); - /// assert_eq!(option_json["url"], Value::Null); + /// assert_eq!(json, expected); /// ``` - pub fn new() -> Self { - Self::default() + pub fn set_text(self, text: Option) -> Self { + Self { text, ..self } } - /// Sets text field. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::{Opt, Text}; - /// use serde_json::json; + /// Set plain text object to text field. + /// If you want to set markdown text object, use `set_text` method instead. /// - /// let option = Opt::new() - /// .set_text(Text::plain("This is a plain text.")); + /// ``` + /// # use slack_messaging::blocks::elements::Opt; + /// let option = Opt::builder() + /// .text("This is a plain text.") + /// .value("") + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "text": { /// "type": "plain_text", - /// "text": "This is a plain text.", - /// "emoji": true + /// "text": "This is a plain text." /// }, /// "value": "" /// }); /// - /// let option_json = serde_json::to_value(option).unwrap(); + /// let json = serde_json::to_value(option).unwrap(); /// - /// assert_eq!(option_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_text(self, text: Text) -> Self { - Self { text, ..self } + pub fn text(self, text: impl Into) -> Self { + let text = Text::builder() + .plain_text(text.into()) + .build(); + self.set_text(Some(text)) } - /// Sets text field. + /// Set value field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::Opt; - /// use serde_json::json; - /// - /// let option = Opt::new().set_value("valueeeeeee"); + /// ``` + /// # use slack_messaging::blocks::elements::Opt; + /// let option = Opt::builder() + /// .text("") + /// .set_value(Some("valueeeeeee".into())) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "" /// }, /// "value": "valueeeeeee" /// }); /// - /// let option_json = serde_json::to_value(option).unwrap(); + /// let json = serde_json::to_value(option).unwrap(); /// - /// assert_eq!(option_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_value>(self, value: T) -> Self { + pub fn set_value(self, value: Option) -> Self { Self { - value: value.into(), + value, ..self } } - /// Sets description field with plain_text object. + /// Set value field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Opt; + /// let option = Opt::builder() + /// .text("") + /// .value("valueeeeeee") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "text": { + /// "type": "plain_text", + /// "text": "" + /// }, + /// "value": "valueeeeeee" + /// }); /// - /// ```ignore - /// use slack_messaging::blocks::elements::Opt; - /// use serde_json::json; + /// let json = serde_json::to_value(option).unwrap(); /// - /// let option = Opt::new().set_description("This is a description."); + /// assert_eq!(json, expected); + /// ``` + pub fn value(self, value: impl Into) -> Self { + self.set_value(Some(value.into())) + } + + /// Set description field. /// - /// let expected = json!({ + /// ``` + /// # use slack_messaging::plain_text; + /// # use slack_messaging::blocks::elements::Opt; + /// let text = plain_text!("This is a description."); + /// let option = Opt::builder() + /// .text("") + /// .value("") + /// .set_description(Some(text)) + /// .build(); + /// + /// let expected = serde_json::json!({ /// "text": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "" /// }, /// "value": "", /// "description": { /// "type": "plain_text", - /// "text": "This is a description.", - /// "emoji": true + /// "text": "This is a description." /// } /// }); /// - /// let option_json = serde_json::to_value(option).unwrap(); + /// let json = serde_json::to_value(option).unwrap(); /// - /// assert_eq!(option_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_description(self, description: Text) -> Self { + pub fn set_description(self, description: Option) -> Self { Self { - description: Some(description), + description, ..self } } - /// Sets url field. + /// Set plain text object to description field. + /// If you want to set markdown text object, use `set_text` method instead. /// - /// ```ignore - /// use slack_messaging::blocks::elements::Opt; - /// use serde_json::{json, Value}; + /// ``` + /// # use slack_messaging::blocks::elements::Opt; + /// let option = Opt::builder() + /// .text("") + /// .value("") + /// .description("This is a description.") + /// .build(); /// - /// let option = Opt::new().set_url("https://google.com"); - /// let option_json = serde_json::to_value(option).unwrap(); + /// let expected = serde_json::json!({ + /// "text": { + /// "type": "plain_text", + /// "text": "" + /// }, + /// "value": "", + /// "description": { + /// "type": "plain_text", + /// "text": "This is a description." + /// } + /// }); + /// + /// let json = serde_json::to_value(option).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn description(self, description: impl Into) -> Self { + let text = Text::builder() + .plain_text(description) + .build(); + self.set_description(Some(text)) + } + + /// Set url field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Opt; + /// let option = Opt::builder() + /// .text("") + /// .value("") + /// .set_url(Some("https://google.com".into())) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "text": { + /// "type": "plain_text", + /// "text": "" + /// }, + /// "value": "", + /// "url": "https://google.com" + /// }); + /// + /// let json = serde_json::to_value(option).unwrap(); /// - /// assert_eq!(option_json["url"], Value::String("https://google.com".into())); + /// assert_eq!(json, expected); /// ``` - pub fn set_url>(self, url: T) -> Self { + pub fn set_url(self, url: Option) -> Self { Self { - url: Some(url.into()), + url, ..self } } + + /// Set url field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Opt; + /// let option = Opt::builder() + /// .text("") + /// .value("") + /// .url("https://google.com") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "text": { + /// "type": "plain_text", + /// "text": "" + /// }, + /// "value": "", + /// "url": "https://google.com" + /// }); + /// + /// let json = serde_json::to_value(option).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn url(self, url: impl Into) -> Self { + self.set_url(Some(url.into())) + } + + /// Build a [`Opt`] object. This method will panic if both + /// `text` and `value` are not set. + pub fn build(self) -> Opt { + Opt { + text: self.text.expect("text must be set to OptBuilder"), + value: self.value.expect("value must be set to OptBuilder"), + description: self.description, + url: self.url, + } + } } diff --git a/src/blocks/elements/opt_group.rs b/src/blocks/elements/opt_group.rs index f32f410..ac20fc1 100644 --- a/src/blocks/elements/opt_group.rs +++ b/src/blocks/elements/opt_group.rs @@ -1,6 +1,4 @@ -use super::Opt; -use super::Text; -use crate::plain_text; +use super::{Opt, Text}; use serde::Serialize; /// [Option group object](https://api.slack.com/reference/block-kit/composition-objects#option_group) @@ -8,47 +6,50 @@ use serde::Serialize; /// /// # Example /// -/// ```ignore -/// use slack_messaging::blocks::elements::{OptGroup, Opt}; -/// use serde_json::json; -/// -/// let options = OptGroup::new() +/// ``` +/// # use slack_messaging::blocks::elements::{OptGroup, Opt}; +/// let options = OptGroup::builder() /// .label("Group One") -/// .push_option( -/// Opt::plain("This is a plain text.").set_value("value-0") +/// .option( +/// Opt::builder() +/// .text("option-0") +/// .value("value-0") +/// .build() /// ) -/// .push_option( -/// Opt::mrkdwn("*This is a mrkdwn text.*").set_value("value-1") -/// ); +/// .option( +/// Opt::builder() +/// .text("option-1") +/// .value("value-1") +/// .build() +/// ) +/// .build(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "label": { /// "type": "plain_text", -/// "text": "Group One", -/// "emoji": true +/// "text": "Group One" /// }, /// "options": [ /// { /// "text": { /// "type": "plain_text", -/// "text": "This is a plain text.", -/// "emoji": true +/// "text": "option-0", /// }, /// "value": "value-0" /// }, /// { /// "text": { -/// "type": "mrkdwn", -/// "text": "*This is a mrkdwn text.*" +/// "type": "plain_text", +/// "text": "option-1" /// }, /// "value": "value-1" /// }, /// ] /// }); /// -/// let options_json = serde_json::to_value(options).unwrap(); +/// let json = serde_json::to_value(options).unwrap(); /// -/// assert_eq!(options_json, expected); +/// assert_eq!(json, expected); /// ``` #[derive(Debug, Clone, Serialize)] pub struct OptGroup { @@ -56,147 +57,159 @@ pub struct OptGroup { options: Vec, } -impl Default for OptGroup { - fn default() -> Self { - Self { - label: plain_text!(""), - options: vec![], - } +impl OptGroup { + /// Construct a [`OptGroupBuilder`]. + pub fn builder() -> OptGroupBuilder { + OptGroupBuilder::default() } } -impl OptGroup { - /// Constructs a Option group object with empty values. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::OptGroup; - /// use serde_json::json; - /// - /// let options = OptGroup::new(); +/// Builder for [`OptGroup`] object. +#[derive(Debug, Default)] +pub struct OptGroupBuilder { + label: Option, + options: Vec, +} + +impl OptGroupBuilder { + /// Set label field. /// - /// let expected = json!({ + /// ``` + /// # use slack_messaging::plain_text; + /// # use slack_messaging::blocks::elements::OptGroup; + /// let text = plain_text!("Group One"); + /// let options = OptGroup::builder() + /// .set_label(Some(text)) + /// .build(); + /// + /// let expected = serde_json::json!({ /// "label": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "Group One" /// }, /// "options": [] /// }); /// - /// let options_json = serde_json::to_value(options).unwrap(); + /// let json = serde_json::to_value(options).unwrap(); /// - /// assert_eq!(options_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn new() -> Self { - Self::default() + pub fn set_label(self, label: Option) -> Self { + Self { label, ..self } } - /// Sets label field with Text object. + /// Set label field. /// - /// ```ignore - /// use slack_messaging::blocks::elements::{OptGroup, Text}; - /// use serde_json::json; - /// - /// let options = OptGroup::new().set_label(Text::plain("Group One")); + /// ``` + /// # use slack_messaging::blocks::elements::OptGroup; + /// let options = OptGroup::builder() + /// .label("Group One") + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "label": { /// "type": "plain_text", - /// "text": "Group One", - /// "emoji": true + /// "text": "Group One" /// }, /// "options": [] /// }); /// - /// let options_json = serde_json::to_value(options).unwrap(); + /// let json = serde_json::to_value(options).unwrap(); /// - /// assert_eq!(options_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_label(self, label: Text) -> Self { - Self { label, ..self } + pub fn label(self, label: impl Into) -> Self { + let text = Text::builder() + .plain_text(label.into()) + .build(); + self.set_label(Some(text)) } - /// Sets options field directly. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::{OptGroup, Opt}; - /// use serde_json::json; + /// Set options field. /// - /// let options = OptGroup::new() + /// ``` + /// # use slack_messaging::blocks::elements::{OptGroup, Opt}; + /// let options = OptGroup::builder() + /// .label("") /// .set_options( /// vec![ - /// Opt::plain("This is a plain text.").set_value("value-0"), - /// Opt::mrkdwn("*This is a mrkdwn text.*").set_value("value-1"), + /// Opt::builder() + /// .text("option-0") + /// .value("value-0") + /// .build(), /// ] - /// ); + /// ) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "label": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "" /// }, /// "options": [ /// { /// "text": { /// "type": "plain_text", - /// "text": "This is a plain text.", - /// "emoji": true + /// "text": "option-0" /// }, /// "value": "value-0" - /// }, - /// { - /// "text": { - /// "type": "mrkdwn", - /// "text": "*This is a mrkdwn text.*" - /// }, - /// "value": "value-1" /// } /// ] /// }); /// - /// let options_json = serde_json::to_value(options).unwrap(); + /// let json = serde_json::to_value(options).unwrap(); /// - /// assert_eq!(options_json, expected); + /// assert_eq!(json, expected); /// ``` pub fn set_options(self, options: Vec) -> Self { Self { options, ..self } } - /// Adds Option object to options field. - /// - /// ```ignore - /// use slack_messaging::blocks::elements::{OptGroup, Opt}; - /// use serde_json::json; + /// Add Option object to options field. /// - /// let options = OptGroup::new() - /// .push_option(Opt::plain("This is a plain text.").set_value("value-0")); - /// - /// let expected = json!({ + /// ``` + /// # use slack_messaging::blocks::elements::{OptGroup, Opt}; + /// let options = OptGroup::builder() + /// .label("") + /// .option( + /// Opt::builder() + /// .text("option-0") + /// .value("value-0") + /// .build(), + /// ) + /// .build(); + /// + /// let expected = serde_json::json!({ /// "label": { /// "type": "plain_text", - /// "text": "", - /// "emoji": true + /// "text": "" /// }, /// "options": [ /// { /// "text": { /// "type": "plain_text", - /// "text": "This is a plain text.", - /// "emoji": true + /// "text": "option-0" /// }, /// "value": "value-0" /// } /// ] /// }); /// - /// let options_json = serde_json::to_value(options).unwrap(); + /// let json = serde_json::to_value(options).unwrap(); /// - /// assert_eq!(options_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn push_option(self, option: Opt) -> Self { + pub fn option(self, option: Opt) -> Self { let Self { mut options, .. } = self; options.push(option); Self { options, ..self } } + + /// Build a [`OptGroup`] object. This method will panic if `label` is not set. + pub fn build(self) -> OptGroup { + OptGroup { + label: self.label.expect("label must be set to OptGroupBuilder"), + options: self.options, + } + } } diff --git a/src/blocks/elements/slack_file.rs b/src/blocks/elements/slack_file.rs new file mode 100644 index 0000000..691fa4d --- /dev/null +++ b/src/blocks/elements/slack_file.rs @@ -0,0 +1,137 @@ +use serde::Serialize; + +/// [Slack file object](https://api.slack.com/reference/block-kit/composition-objects#slack_file) +/// representation. +/// +/// # Example +/// +/// ``` +/// # use slack_messaging::blocks::elements::SlackFile; +/// let file = SlackFile::builder() +/// .id("F0123456") +/// .build(); +/// +/// let expected = serde_json::json!({ +/// "id": "F0123456" +/// }); +/// +/// let json = serde_json::to_value(file).unwrap(); +/// +/// assert_eq!(json, expected); +/// ``` +#[derive(Debug, Clone, Serialize)] +pub struct SlackFile { + #[serde(skip_serializing_if = "Option::is_none")] + id: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + url: Option, +} + +impl SlackFile { + /// Construct a [`SlackFileBuilder`]. + pub fn builder() -> SlackFileBuilder { + SlackFileBuilder::default() + } +} + +/// Builder for [`SlackFile`] object. +#[derive(Debug, Default)] +pub struct SlackFileBuilder { + id: Option, + url: Option, +} + +impl SlackFileBuilder { + /// Set id field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::SlackFile; + /// let file = SlackFile::builder() + /// .set_id(Some("F0123456".into())) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "id": "F0123456" + /// }); + /// + /// let json = serde_json::to_value(file).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_id(self, id: Option) -> Self { + Self { id, ..self } + } + + /// Set id field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::SlackFile; + /// let file = SlackFile::builder() + /// .id("F0123456") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "id": "F0123456" + /// }); + /// + /// let json = serde_json::to_value(file).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn id(self, id: impl Into) -> Self { + self.set_id(Some(id.into())) + } + + /// Set url field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::SlackFile; + /// let file = SlackFile::builder() + /// .set_url(Some("https://files.slack.com/files-pri/T0123456-F0123456/xyz.png".into())) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "url": "https://files.slack.com/files-pri/T0123456-F0123456/xyz.png" + /// }); + /// + /// let json = serde_json::to_value(file).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_url(self, url: Option) -> Self { + Self { url, ..self } + } + + /// Set url field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::SlackFile; + /// let file = SlackFile::builder() + /// .url("https://files.slack.com/files-pri/T0123456-F0123456/xyz.png") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "url": "https://files.slack.com/files-pri/T0123456-F0123456/xyz.png" + /// }); + /// + /// let json = serde_json::to_value(file).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn url(self, url: impl Into) -> Self { + self.set_url(Some(url.into())) + } + + /// Build a [`SlackFile`] object. This method will panic if neither `id` nor `url` are set. + pub fn build(self) -> SlackFile { + if self.id.is_none() && self.url.is_none() { + panic!("Either id or url must be set to SlackFileBuilder"); + } + + SlackFile { + id: self.id, + url: self.url + } + } +} diff --git a/src/blocks/elements/text.rs b/src/blocks/elements/text.rs index 03918f1..c6c20bf 100644 --- a/src/blocks/elements/text.rs +++ b/src/blocks/elements/text.rs @@ -13,8 +13,7 @@ const TYPE_MRKDWN: &str = "mrkdwn"; /// ``` /// # use slack_messaging::blocks::elements::Text; /// let text = Text::builder() -/// .plain_text() -/// .set_text("Hello, World!") +/// .plain_text("Hello, World!") /// .build(); /// /// let json = serde_json::to_value(text).unwrap(); @@ -32,8 +31,7 @@ const TYPE_MRKDWN: &str = "mrkdwn"; /// ``` /// # use slack_messaging::blocks::elements::Text; /// let text = Text::builder() -/// .mrkdwn() -/// .set_text("Hello, World!") +/// .mrkdwn("Hello, World!") /// .build(); /// let json = serde_json::to_value(text).unwrap(); /// @@ -59,7 +57,7 @@ pub struct Text { } impl Text { - /// Constructs a [`TextBuilder`]. + /// Construct a [`TextBuilder`]. pub fn builder() -> TextBuilder { TextBuilder::default() } @@ -79,6 +77,7 @@ impl PartialEq for Text { } } +/// Builder for [`Text`] object. #[derive(Debug, Default)] pub struct TextBuilder { kind: Option<&'static str>, @@ -88,14 +87,12 @@ pub struct TextBuilder { } impl TextBuilder { - /// Turns self into a `plain_text` text object. Either `plain_text` or `mrkdwn` method must - /// be called before the `build` method is called. + /// Set plain text. /// /// ``` /// # use slack_messaging::blocks::elements::Text; /// let text = Text::builder() - /// .plain_text() - /// .set_text("hello world") + /// .plain_text("hello world") /// .build(); /// /// let expected = serde_json::json!({ @@ -106,21 +103,40 @@ impl TextBuilder { /// let json = serde_json::to_value(text).unwrap(); /// assert_eq!(json, expected); /// ``` - pub fn plain_text(self) -> Self { + pub fn plain_text(self, text: impl Into) -> Self { + self.set_plain_text(Some(text.into())) + } + + /// Set plain text. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Text; + /// let text = Text::builder() + /// .set_plain_text(Some("hello world".into())) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "type": "plain_text", + /// "text": "hello world", + /// }); + /// + /// let json = serde_json::to_value(text).unwrap(); + /// assert_eq!(json, expected); + /// ``` + pub fn set_plain_text(self, text: Option) -> Self { Self { kind: Some(TYPE_PLAIN), + text, ..self } } - /// Turns self into a `mrkdwn` text object. Either `plain_text` or `mrkdwn` method must - /// be called before the `build` method is called. + /// Set markdown text. /// /// ``` /// # use slack_messaging::blocks::elements::Text; /// let text = Text::builder() - /// .mrkdwn() - /// .set_text("hello world") + /// .mrkdwn("hello world") /// .build(); /// /// let expected = serde_json::json!({ @@ -131,45 +147,41 @@ impl TextBuilder { /// let json = serde_json::to_value(text).unwrap(); /// assert_eq!(json, expected); /// ``` - pub fn mrkdwn(self) -> Self { - Self { - kind: Some(TYPE_MRKDWN), - ..self - } + pub fn mrkdwn(self, text: impl Into) -> Self { + self.set_mrkdwn(Some(text.into())) } - /// Sets text field. This method must be called before the `build` method is called. + /// Set markdown text. /// /// ``` /// # use slack_messaging::blocks::elements::Text; /// let text = Text::builder() - /// .plain_text() - /// .set_text("hello world") + /// .set_mrkdwn(Some("hello world".into())) /// .build(); /// /// let expected = serde_json::json!({ - /// "type": "plain_text", + /// "type": "mrkdwn", /// "text": "hello world", /// }); /// /// let json = serde_json::to_value(text).unwrap(); /// assert_eq!(json, expected); /// ``` - pub fn set_text(self, text: impl Into) -> Self { + pub fn set_mrkdwn(self, text: Option) -> Self { Self { - text: Some(text.into()), + kind: Some(TYPE_MRKDWN), + text, ..self } } - /// Sets emoji field. + /// Set emoji field. /// /// ``` /// # use slack_messaging::blocks::elements::Text; /// let text = Text::builder() - /// .plain_text() - /// .set_emoji(true) - /// .set_text("😊") + /// .plain_text("😊") + /// .emoji(true) /// .build(); /// /// let expected = serde_json::json!({ @@ -181,21 +193,39 @@ impl TextBuilder { /// let json = serde_json::to_value(text).unwrap(); /// assert_eq!(json, expected); /// ``` - pub fn set_emoji(self, emoji: bool) -> Self { - Self { - emoji: Some(emoji), - ..self - } + pub fn emoji(self, emoji: bool) -> Self { + self.set_emoji(Some(emoji)) } - /// Sets verbatim field. + /// Set emoji field. /// /// ``` /// # use slack_messaging::blocks::elements::Text; /// let text = Text::builder() - /// .mrkdwn() - /// .set_text("hello world") - /// .set_verbatim(true) + /// .plain_text("😊") + /// .set_emoji(Some(true)) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "type": "plain_text", + /// "text": "😊", + /// "emoji": true + /// }); + /// + /// let json = serde_json::to_value(text).unwrap(); + /// assert_eq!(json, expected); + /// ``` + pub fn set_emoji(self, emoji: Option) -> Self { + Self { emoji, ..self } + } + + /// Set verbatim field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::Text; + /// let text = Text::builder() + /// .mrkdwn("hello world") + /// .verbatim(true) /// .build(); /// /// let expected = serde_json::json!({ @@ -207,34 +237,37 @@ impl TextBuilder { /// let json = serde_json::to_value(text).unwrap(); /// assert_eq!(json, expected); /// ``` - pub fn set_verbatim(self, verbatim: bool) -> Self { - Self { - verbatim: Some(verbatim), - ..self - } + pub fn verbatim(self, verbatim: bool) -> Self { + self.set_verbatim(Some(verbatim)) } - /// Build a [`Text`] object. This method will panic if either `type` of `text` is not set. + /// Set verbatim field. /// /// ``` /// # use slack_messaging::blocks::elements::Text; /// let text = Text::builder() - /// .plain_text() - /// .set_text("hello world") + /// .mrkdwn("hello world") + /// .set_verbatim(Some(true)) /// .build(); /// /// let expected = serde_json::json!({ - /// "type": "plain_text", - /// "text": "hello world", + /// "type": "mrkdwn", + /// "text": "hello world", + /// "verbatim": true /// }); /// /// let json = serde_json::to_value(text).unwrap(); /// assert_eq!(json, expected); /// ``` + pub fn set_verbatim(self, verbatim: Option) -> Self { + Self { verbatim, ..self } + } + + /// Build a [`Text`] object. This method will panic if either `type` of `text` is not set. pub fn build(self) -> Text { Text { - kind: self.kind.expect("text type must be set"), - text: self.text.expect("text must be set"), + kind: self.kind.expect("text type must be set to TextBuilder"), + text: self.text.expect("text must be set to TextBuilder"), emoji: self.emoji, verbatim: self.verbatim, } @@ -247,13 +280,13 @@ mod tests { #[test] fn it_equals_with_same_type_and_text() { - let plain_0 = Text::builder().plain_text().set_text("Hello").build(); - let plain_1 = Text::builder().plain_text().set_text("Hello").build(); - let plain_2 = Text::builder().plain_text().set_text("hello").build(); + let plain_0 = Text::builder().plain_text("Hello").build(); + let plain_1 = Text::builder().plain_text("Hello").build(); + let plain_2 = Text::builder().plain_text("hello").build(); - let mrkdwn_0 = Text::builder().mrkdwn().set_text("Hello").build(); - let mrkdwn_1 = Text::builder().mrkdwn().set_text("Hello").build(); - let mrkdwn_2 = Text::builder().mrkdwn().set_text("hello").build(); + let mrkdwn_0 = Text::builder().mrkdwn("Hello").build(); + let mrkdwn_1 = Text::builder().mrkdwn("Hello").build(); + let mrkdwn_2 = Text::builder().mrkdwn("hello").build(); assert_eq!(plain_0, plain_1); assert_eq!(mrkdwn_0, mrkdwn_1); @@ -269,50 +302,26 @@ mod tests { #[test] fn it_compares_emoji_field_when_plain_text() { - let plain_0 = Text::builder() - .plain_text() - .set_text("Hello") - .set_emoji(false) - .build(); - let plain_1 = Text::builder().plain_text().set_text("Hello").build(); + let plain_0 = Text::builder().plain_text("Hello").emoji(false).build(); + let plain_1 = Text::builder().plain_text("Hello").build(); assert_ne!(plain_0, plain_1); - let plain_0 = Text::builder() - .plain_text() - .set_text("Hello") - .set_emoji(false) - .build(); - let plain_1 = Text::builder() - .plain_text() - .set_text("Hello") - .set_emoji(false) - .build(); + let plain_0 = Text::builder().plain_text("Hello").emoji(false).build(); + let plain_1 = Text::builder().plain_text("Hello").emoji(false).build(); assert_eq!(plain_0, plain_1); } #[test] fn it_compares_verbatim_field_when_mrkdwn() { - let mrkdwn_0 = Text::builder() - .mrkdwn() - .set_text("Hello") - .set_verbatim(true) - .build(); - let mrkdwn_1 = Text::builder().mrkdwn().set_text("Hello").build(); + let mrkdwn_0 = Text::builder().mrkdwn("Hello").verbatim(true).build(); + let mrkdwn_1 = Text::builder().mrkdwn("Hello").build(); assert_ne!(mrkdwn_0, mrkdwn_1); - let mrkdwn_0 = Text::builder() - .mrkdwn() - .set_text("Hello") - .set_verbatim(true) - .build(); - let mrkdwn_1 = Text::builder() - .mrkdwn() - .set_text("Hello") - .set_verbatim(true) - .build(); + let mrkdwn_0 = Text::builder().mrkdwn("Hello").verbatim(true).build(); + let mrkdwn_1 = Text::builder().mrkdwn("Hello").verbatim(true).build(); assert_eq!(mrkdwn_0, mrkdwn_1); } diff --git a/src/blocks/elements/trigger.rs b/src/blocks/elements/trigger.rs new file mode 100644 index 0000000..7c218ff --- /dev/null +++ b/src/blocks/elements/trigger.rs @@ -0,0 +1,189 @@ +use super::InputParameter; +use serde::Serialize; + +/// [Trigger object](https://api.slack.com/reference/block-kit/composition-objects#trigger) +/// representation. +/// +/// # Example +/// +/// ``` +/// # use slack_messaging::blocks::elements::{InputParameter, Trigger}; +/// let trigger = Trigger::builder() +/// .url("https://slack.com/shortcuts/Ft0123ABC456/123...xyz") +/// .customizable_input_parameter( +/// InputParameter::builder() +/// .name("input_parameter_a") +/// .value("Value for input param A") +/// .build() +/// ) +/// .customizable_input_parameter( +/// InputParameter::builder() +/// .name("input_parameter_b") +/// .value("Value for input param B") +/// .build() +/// ) +/// .build(); +/// +/// let expected = serde_json::json!({ +/// "url": "https://slack.com/shortcuts/Ft0123ABC456/123...xyz", +/// "customizable_input_parameters": [ +/// { +/// "name": "input_parameter_a", +/// "value": "Value for input param A" +/// }, +/// { +/// "name": "input_parameter_b", +/// "value": "Value for input param B" +/// } +/// ] +/// }); +/// +/// let json = serde_json::to_value(trigger).unwrap(); +/// +/// assert_eq!(json, expected); +/// ``` +#[derive(Debug, Clone, Serialize)] +pub struct Trigger { + url: String, + + #[serde(skip_serializing_if = "Vec::is_empty")] + customizable_input_parameters: Vec, +} + +impl Trigger { + /// Construct a [`TriggerBuilder`]. + pub fn builder() -> TriggerBuilder { + TriggerBuilder::default() + } +} + +/// Builder for [`Trigger`] object. +#[derive(Debug, Default)] +pub struct TriggerBuilder { + url: Option, + customizable_input_parameters: Vec, +} + +impl TriggerBuilder { + /// Set url field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::{InputParameter, Trigger}; + /// let trigger = Trigger::builder() + /// .set_url(Some("https://slack.com/shortcuts/Ft0123ABC456/123...xyz".into())) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "url": "https://slack.com/shortcuts/Ft0123ABC456/123...xyz" + /// }); + /// + /// let json = serde_json::to_value(trigger).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_url(self, url: Option) -> Self { + Self { url, ..self } + } + + /// Set url field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::{InputParameter, Trigger}; + /// let trigger = Trigger::builder() + /// .url("https://slack.com/shortcuts/Ft0123ABC456/123...xyz") + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "url": "https://slack.com/shortcuts/Ft0123ABC456/123...xyz" + /// }); + /// + /// let json = serde_json::to_value(trigger).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn url(self, url: impl Into) -> Self { + self.set_url(Some(url.into())) + } + + /// Set customizable_input_parameters field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::{InputParameter, Trigger}; + /// let trigger = Trigger::builder() + /// .url("") + /// .set_customizable_input_parameters( + /// vec![ + /// InputParameter::builder() + /// .name("input_parameter_a") + /// .value("Value for input param A") + /// .build() + /// ] + /// ) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "url": "", + /// "customizable_input_parameters": [ + /// { + /// "name": "input_parameter_a", + /// "value": "Value for input param A" + /// } + /// ] + /// }); + /// + /// let json = serde_json::to_value(trigger).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_customizable_input_parameters( + self, + customizable_input_parameters: Vec, + ) -> Self { + Self { customizable_input_parameters, ..self } + } + + /// Add input parameter object to customizable_input_parameters field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::{InputParameter, Trigger}; + /// let trigger = Trigger::builder() + /// .url("") + /// .customizable_input_parameter( + /// InputParameter::builder() + /// .name("input_parameter_a") + /// .value("Value for input param A") + /// .build() + /// ) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "url": "", + /// "customizable_input_parameters": [ + /// { + /// "name": "input_parameter_a", + /// "value": "Value for input param A" + /// } + /// ] + /// }); + /// + /// let json = serde_json::to_value(trigger).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn customizable_input_parameter( + self, + customizable_input_parameter: InputParameter, + ) -> Self { + let Self { mut customizable_input_parameters, .. } = self; + customizable_input_parameters.push(customizable_input_parameter); + Self { customizable_input_parameters, ..self } + } + + /// Build a [`Trigger`] object. This method will panic if `url` is not set. + pub fn build(self) -> Trigger { + Trigger { + url: self.url.expect("url must be set to TriggerBuilder"), + customizable_input_parameters: self.customizable_input_parameters, + } + } +} diff --git a/src/blocks/elements/workflow.rs b/src/blocks/elements/workflow.rs new file mode 100644 index 0000000..58a6a64 --- /dev/null +++ b/src/blocks/elements/workflow.rs @@ -0,0 +1,128 @@ +use super::Trigger; +use serde::Serialize; + +/// [Workflow object](https://api.slack.com/reference/block-kit/composition-objects#workflow) +/// representation. +/// +/// # Example +/// +/// ``` +/// # use slack_messaging::blocks::elements::{InputParameter, Trigger, Workflow}; +/// let workflow = Workflow::builder() +/// .trigger( +/// Trigger::builder() +/// .url("https://slack.com/shortcuts/Ft0123ABC456/123...xyz") +/// .customizable_input_parameter( +/// InputParameter::builder() +/// .name("input_parameter_a") +/// .value("Value for input param A") +/// .build() +/// ) +/// .customizable_input_parameter( +/// InputParameter::builder() +/// .name("input_parameter_b") +/// .value("Value for input param B") +/// .build() +/// ) +/// .build() +/// ) +/// .build(); +/// +/// let expected = serde_json::json!({ +/// "trigger": { +/// "url": "https://slack.com/shortcuts/Ft0123ABC456/123...xyz", +/// "customizable_input_parameters": [ +/// { +/// "name": "input_parameter_a", +/// "value": "Value for input param A" +/// }, +/// { +/// "name": "input_parameter_b", +/// "value": "Value for input param B" +/// } +/// ] +/// } +/// }); +/// +/// let json = serde_json::to_value(workflow).unwrap(); +/// +/// assert_eq!(json, expected); +/// ``` +#[derive(Debug, Clone, Serialize)] +pub struct Workflow { + trigger: Trigger, +} + +impl Workflow { + /// Construct a [`WorkflowBuilder`]. + pub fn builder() -> WorkflowBuilder { + WorkflowBuilder::default() + } +} + +/// Builder for [`Workflow`] object. +#[derive(Debug, Default)] +pub struct WorkflowBuilder { + trigger: Option, +} + +impl WorkflowBuilder { + /// Set trigger field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::{InputParameter, Trigger, Workflow}; + /// let workflow = Workflow::builder() + /// .set_trigger( + /// Some(Trigger::builder() + /// .url("https://slack.com/shortcuts/Ft0123ABC456/123...xyz") + /// .build()) + /// ) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "trigger": { + /// "url": "https://slack.com/shortcuts/Ft0123ABC456/123...xyz" + /// } + /// }); + /// + /// let json = serde_json::to_value(workflow).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn set_trigger(self, trigger: Option) -> Self { + Self { trigger, ..self } + } + + /// Set trigger field. + /// + /// ``` + /// # use slack_messaging::blocks::elements::{InputParameter, Trigger, Workflow}; + /// let workflow = Workflow::builder() + /// .trigger( + /// Trigger::builder() + /// .url("https://slack.com/shortcuts/Ft0123ABC456/123...xyz") + /// .build() + /// ) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "trigger": { + /// "url": "https://slack.com/shortcuts/Ft0123ABC456/123...xyz" + /// } + /// }); + /// + /// let json = serde_json::to_value(workflow).unwrap(); + /// + /// assert_eq!(json, expected); + /// ``` + pub fn trigger(self, trigger: Trigger) -> Self { + self.set_trigger(Some(trigger)) + } + + /// Build a [`Workflow`] object. This method will panic if `trigger` is not set. + pub fn build(self) -> Workflow { + Workflow { + trigger: self.trigger.expect("trigger must be set to WorkflowBuilder"), + } + } +} diff --git a/src/macros.rs b/src/macros.rs index 2d99f1c..aa64cbc 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -5,8 +5,7 @@ /// # use slack_messaging::blocks::elements::Text; /// let text = plain_text!("Hello, World!"); /// let expected = Text::builder() -/// .plain_text() -/// .set_text("Hello, World!") +/// .plain_text("Hello, World!") /// .build(); /// /// assert_eq!(text, expected); @@ -17,8 +16,7 @@ /// /// let text = plain_text!("{}, {}!", greet, name); /// let expected = Text::builder() -/// .plain_text() -/// .set_text("Hi, Tanaka!") +/// .plain_text("Hi, Tanaka!") /// .build(); /// /// assert_eq!(text, expected); @@ -27,14 +25,12 @@ macro_rules! plain_text { ($fmt:expr) => { $crate::blocks::elements::Text::builder() - .plain_text() - .set_text(format!($fmt)) + .plain_text(format!($fmt)) .build() }; ($fmt:expr, $($arg:tt)+) => { $crate::blocks::elements::Text::builder() - .plain_text() - .set_text(format!($fmt, $($arg)+)) + .plain_text(format!($fmt, $($arg)+)) .build() }; } @@ -46,8 +42,7 @@ macro_rules! plain_text { /// # use slack_messaging::blocks::elements::Text; /// let text = mrkdwn!("Hello, World!"); /// let expected = Text::builder() -/// .mrkdwn() -/// .set_text("Hello, World!") +/// .mrkdwn("Hello, World!") /// .build(); /// /// assert_eq!(text, expected); @@ -58,8 +53,7 @@ macro_rules! plain_text { /// /// let text = mrkdwn!("{}, {}!", greet, name); /// let expected = Text::builder() -/// .mrkdwn() -/// .set_text("Hi, Tanaka!") +/// .mrkdwn("Hi, Tanaka!") /// .build(); /// /// assert_eq!(text, expected); @@ -68,14 +62,12 @@ macro_rules! plain_text { macro_rules! mrkdwn { ($fmt:expr) => { $crate::blocks::elements::Text::builder() - .mrkdwn() - .set_text(format!($fmt)) + .mrkdwn(format!($fmt)) .build() }; ($fmt:expr, $($arg:tt)+) => { $crate::blocks::elements::Text::builder() - .mrkdwn() - .set_text(format!($fmt, $($arg)+)) + .mrkdwn(format!($fmt, $($arg)+)) .build() }; } @@ -87,10 +79,7 @@ mod tests { #[test] fn it_works_macro_plain_text_given_expression() { let text = plain_text!("Hello, Tanaka!"); - let expected = Text::builder() - .plain_text() - .set_text("Hello, Tanaka!") - .build(); + let expected = Text::builder().plain_text("Hello, Tanaka!").build(); assert_eq!(text, expected); } @@ -98,17 +87,14 @@ mod tests { fn it_works_macro_plain_text_given_expression_and_tokens() { let name = "Tanaka"; let text = plain_text!("Hello, {}!", name); - let expected = Text::builder() - .plain_text() - .set_text("Hello, Tanaka!") - .build(); + let expected = Text::builder().plain_text("Hello, Tanaka!").build(); assert_eq!(text, expected); } #[test] fn it_works_macro_mrkdwn_given_expression() { let text = mrkdwn!("Hello, Tanaka!"); - let expected = Text::builder().mrkdwn().set_text("Hello, Tanaka!").build(); + let expected = Text::builder().mrkdwn("Hello, Tanaka!").build(); assert_eq!(text, expected); } @@ -116,7 +102,7 @@ mod tests { fn it_works_macro_mrkdwn_given_expression_and_tokens() { let name = "Tanaka"; let text = mrkdwn!("Hello, {}!", name); - let expected = Text::builder().mrkdwn().set_text("Hello, Tanaka!").build(); + let expected = Text::builder().mrkdwn("Hello, Tanaka!").build(); assert_eq!(text, expected); } } From 8d9f46bdea7d583f417c227952e3267021c1898a Mon Sep 17 00:00:00 2001 From: kaicoh Date: Sat, 6 Apr 2024 15:22:59 +0900 Subject: [PATCH 4/9] fmt --- src/blocks/elements/input_parameter.rs | 8 ++++++-- src/blocks/elements/opt.rs | 20 +++++--------------- src/blocks/elements/opt_group.rs | 4 +--- src/blocks/elements/slack_file.rs | 2 +- src/blocks/elements/trigger.rs | 15 ++++++++++++--- src/blocks/elements/workflow.rs | 6 ++++-- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/blocks/elements/input_parameter.rs b/src/blocks/elements/input_parameter.rs index 66582ea..f765b6d 100644 --- a/src/blocks/elements/input_parameter.rs +++ b/src/blocks/elements/input_parameter.rs @@ -136,8 +136,12 @@ impl InputParameterBuilder { /// not set. pub fn build(self) -> InputParameter { InputParameter { - name: self.name.expect("name must be set to InputParameterBuilder"), - value: self.value.expect("value must be set to InputParameterBuilder"), + name: self + .name + .expect("name must be set to InputParameterBuilder"), + value: self + .value + .expect("value must be set to InputParameterBuilder"), } } } diff --git a/src/blocks/elements/opt.rs b/src/blocks/elements/opt.rs index 73acb8b..6d95b54 100644 --- a/src/blocks/elements/opt.rs +++ b/src/blocks/elements/opt.rs @@ -51,7 +51,7 @@ pub struct OptBuilder { text: Option, value: Option, description: Option, - url: Option + url: Option, } impl OptBuilder { @@ -105,9 +105,7 @@ impl OptBuilder { /// assert_eq!(json, expected); /// ``` pub fn text(self, text: impl Into) -> Self { - let text = Text::builder() - .plain_text(text.into()) - .build(); + let text = Text::builder().plain_text(text.into()).build(); self.set_text(Some(text)) } @@ -133,10 +131,7 @@ impl OptBuilder { /// assert_eq!(json, expected); /// ``` pub fn set_value(self, value: Option) -> Self { - Self { - value, - ..self - } + Self { value, ..self } } /// Set value field. @@ -227,9 +222,7 @@ impl OptBuilder { /// assert_eq!(json, expected); /// ``` pub fn description(self, description: impl Into) -> Self { - let text = Text::builder() - .plain_text(description) - .build(); + let text = Text::builder().plain_text(description).build(); self.set_description(Some(text)) } @@ -257,10 +250,7 @@ impl OptBuilder { /// assert_eq!(json, expected); /// ``` pub fn set_url(self, url: Option) -> Self { - Self { - url, - ..self - } + Self { url, ..self } } /// Set url field. diff --git a/src/blocks/elements/opt_group.rs b/src/blocks/elements/opt_group.rs index ac20fc1..919ac8a 100644 --- a/src/blocks/elements/opt_group.rs +++ b/src/blocks/elements/opt_group.rs @@ -119,9 +119,7 @@ impl OptGroupBuilder { /// assert_eq!(json, expected); /// ``` pub fn label(self, label: impl Into) -> Self { - let text = Text::builder() - .plain_text(label.into()) - .build(); + let text = Text::builder().plain_text(label.into()).build(); self.set_label(Some(text)) } diff --git a/src/blocks/elements/slack_file.rs b/src/blocks/elements/slack_file.rs index 691fa4d..c324eec 100644 --- a/src/blocks/elements/slack_file.rs +++ b/src/blocks/elements/slack_file.rs @@ -131,7 +131,7 @@ impl SlackFileBuilder { SlackFile { id: self.id, - url: self.url + url: self.url, } } } diff --git a/src/blocks/elements/trigger.rs b/src/blocks/elements/trigger.rs index 7c218ff..b2224f5 100644 --- a/src/blocks/elements/trigger.rs +++ b/src/blocks/elements/trigger.rs @@ -139,7 +139,10 @@ impl TriggerBuilder { self, customizable_input_parameters: Vec, ) -> Self { - Self { customizable_input_parameters, ..self } + Self { + customizable_input_parameters, + ..self + } } /// Add input parameter object to customizable_input_parameters field. @@ -174,9 +177,15 @@ impl TriggerBuilder { self, customizable_input_parameter: InputParameter, ) -> Self { - let Self { mut customizable_input_parameters, .. } = self; + let Self { + mut customizable_input_parameters, + .. + } = self; customizable_input_parameters.push(customizable_input_parameter); - Self { customizable_input_parameters, ..self } + Self { + customizable_input_parameters, + ..self + } } /// Build a [`Trigger`] object. This method will panic if `url` is not set. diff --git a/src/blocks/elements/workflow.rs b/src/blocks/elements/workflow.rs index 58a6a64..c91673d 100644 --- a/src/blocks/elements/workflow.rs +++ b/src/blocks/elements/workflow.rs @@ -90,7 +90,7 @@ impl WorkflowBuilder { /// assert_eq!(json, expected); /// ``` pub fn set_trigger(self, trigger: Option) -> Self { - Self { trigger, ..self } + Self { trigger } } /// Set trigger field. @@ -122,7 +122,9 @@ impl WorkflowBuilder { /// Build a [`Workflow`] object. This method will panic if `trigger` is not set. pub fn build(self) -> Workflow { Workflow { - trigger: self.trigger.expect("trigger must be set to WorkflowBuilder"), + trigger: self + .trigger + .expect("trigger must be set to WorkflowBuilder"), } } } From 26b5a4f64452be7f95c6c37d67048415311141d4 Mon Sep 17 00:00:00 2001 From: kaicoh Date: Sun, 7 Apr 2024 23:07:01 +0900 Subject: [PATCH 5/9] Apply builder pattern --- src/attachment.rs | 250 ------ src/blocks/actions.rs | 470 +++++------ src/blocks/context.rs | 193 +++-- src/blocks/divider.rs | 90 ++- src/blocks/elements/button.rs | 14 +- src/blocks/elements/checkbox_group.rs | 381 --------- src/blocks/elements/checkboxes.rs | 450 +++++++++++ src/blocks/elements/datepicker.rs | 348 +++++--- src/blocks/elements/datetimepicker.rs | 286 ++++--- src/blocks/elements/email_input.rs | 307 ++++--- src/blocks/elements/file_input.rs | 444 ++++++++++ src/blocks/elements/image.rs | 212 +++-- src/blocks/elements/mod.rs | 32 +- .../elements/multi_select_conversations.rs | 505 ++++++++---- src/blocks/elements/multi_select_externals.rs | 478 +++++++---- .../elements/multi_select_public_channels.rs | 394 +++++---- .../elements/multi_select_static_options.rs | 645 +++++++++------ src/blocks/elements/multi_select_users.rs | 395 +++++---- src/blocks/elements/number_input.rs | 478 +++++++---- src/blocks/elements/overflow_menu.rs | 293 ++++--- src/blocks/elements/plain_text_input.rs | 458 +++++++---- src/blocks/elements/radio_button_group.rs | 401 +++++---- src/blocks/elements/rich_text_input.rs | 406 ++++++++++ src/blocks/elements/select_conversations.rs | 514 +++++++----- src/blocks/elements/select_externals.rs | 413 +++++++--- src/blocks/elements/select_public_channels.rs | 403 ++++++---- src/blocks/elements/select_static_options.rs | 592 ++++++++------ src/blocks/elements/select_users.rs | 345 +++++--- src/blocks/elements/timepicker.rs | 394 ++++++--- src/blocks/elements/url_input.rs | 309 ++++--- src/blocks/elements/workflow_button.rs | 528 ++++++++++++ src/blocks/file.rs | 216 +++++ src/blocks/header.rs | 157 ++-- src/blocks/image.rs | 346 +++++--- src/blocks/input.rs | 760 ++++++++++-------- src/blocks/mod.rs | 73 +- src/blocks/rich_text/elements/list.rs | 438 ++++++++++ src/blocks/rich_text/elements/mod.rs | 47 ++ src/blocks/rich_text/elements/preformatted.rs | 181 +++++ src/blocks/rich_text/elements/quote.rs | 181 +++++ src/blocks/rich_text/elements/section.rs | 179 +++++ .../rich_text/elements/types/channel.rs | 171 ++++ src/blocks/rich_text/elements/types/emoji.rs | 96 +++ src/blocks/rich_text/elements/types/link.rs | 273 +++++++ src/blocks/rich_text/elements/types/mod.rs | 67 ++ src/blocks/rich_text/elements/types/styles.rs | 540 +++++++++++++ src/blocks/rich_text/elements/types/text.rs | 171 ++++ src/blocks/rich_text/elements/types/user.rs | 171 ++++ .../rich_text/elements/types/usergroup.rs | 174 ++++ src/blocks/rich_text/mod.rs | 230 ++++++ src/blocks/section.rs | 484 +++++------ src/blocks/video.rs | 711 +++++++++++----- src/lib.rs | 58 +- src/message.rs | 530 ++++-------- 54 files changed, 12365 insertions(+), 5317 deletions(-) delete mode 100644 src/attachment.rs delete mode 100644 src/blocks/elements/checkbox_group.rs create mode 100644 src/blocks/elements/checkboxes.rs create mode 100644 src/blocks/elements/file_input.rs create mode 100644 src/blocks/elements/rich_text_input.rs create mode 100644 src/blocks/elements/workflow_button.rs create mode 100644 src/blocks/file.rs create mode 100644 src/blocks/rich_text/elements/list.rs create mode 100644 src/blocks/rich_text/elements/mod.rs create mode 100644 src/blocks/rich_text/elements/preformatted.rs create mode 100644 src/blocks/rich_text/elements/quote.rs create mode 100644 src/blocks/rich_text/elements/section.rs create mode 100644 src/blocks/rich_text/elements/types/channel.rs create mode 100644 src/blocks/rich_text/elements/types/emoji.rs create mode 100644 src/blocks/rich_text/elements/types/link.rs create mode 100644 src/blocks/rich_text/elements/types/mod.rs create mode 100644 src/blocks/rich_text/elements/types/styles.rs create mode 100644 src/blocks/rich_text/elements/types/text.rs create mode 100644 src/blocks/rich_text/elements/types/user.rs create mode 100644 src/blocks/rich_text/elements/types/usergroup.rs create mode 100644 src/blocks/rich_text/mod.rs diff --git a/src/attachment.rs b/src/attachment.rs deleted file mode 100644 index 760da7e..0000000 --- a/src/attachment.rs +++ /dev/null @@ -1,250 +0,0 @@ -use super::blocks::Block; -use serde::Serialize; - -/// [Secondary message attachment](https://api.slack.com/reference/messaging/attachments) -/// representation. -/// -/// # Example -/// -/// See also [Context](crate::blocks::Context), [Section](crate::blocks::Section) -/// and [any other blocks](crate::blocks) to know how to build these blocks. -/// -/// ```ignore -/// use slack_messaging::Attachment; -/// use slack_messaging::blocks::{Context, Section}; -/// use slack_messaging::blocks::elements::{Image, Text}; -/// use serde_json::json; -/// -/// let author = Context::new() -/// .push_element( -/// Image::new() -/// .set_image_url("https://placeimg.com/16/16/people") -/// .set_alt_text("author") -/// ) -/// .push_element( -/// Text::mrkdwn("**") -/// ); -/// -/// let content = Section::new() -/// .set_text_mrkdwn("Optional `text` that appears within the attachment") -/// .push_field_mrkdwn("*A 1st field's title*\nA 1st field's value") -/// .push_field_mrkdwn("*A 2nd field's title*\nA 2nd field's value") -/// .set_accessory( -/// Image::new() -/// .set_image_url("http://placekitten.com/g/200/200") -/// .set_alt_text("cute kitten") -/// ); -/// -/// let footer = Context::new() -/// .push_element( -/// Image::new() -/// .set_image_url("https://platform.slack-edge.com/img/default_application_icon.png") -/// .set_alt_text("footer icon") -/// ) -/// .push_element( -/// Text::mrkdwn("footer | ") -/// ); -/// -/// let attachment = Attachment::new() -/// .set_color("#36a64f") -/// .push_block(author) -/// .push_block(content) -/// .push_block(footer); -/// -/// let expected = json!({ -/// "color": "#36a64f", -/// "blocks": [ -/// { -/// "type": "context", -/// "elements": [ -/// { -/// "type": "image", -/// "image_url": "https://placeimg.com/16/16/people", -/// "alt_text": "author" -/// }, -/// { -/// "type": "mrkdwn", -/// "text": "**" -/// } -/// ] -/// }, -/// { -/// "type": "section", -/// "text": { -/// "type": "mrkdwn", -/// "text": "Optional `text` that appears within the attachment" -/// }, -/// "fields": [ -/// { -/// "type": "mrkdwn", -/// "text": "*A 1st field's title*\nA 1st field's value" -/// }, -/// { -/// "type": "mrkdwn", -/// "text": "*A 2nd field's title*\nA 2nd field's value" -/// } -/// ], -/// "accessory": { -/// "type": "image", -/// "image_url": "http://placekitten.com/g/200/200", -/// "alt_text": "cute kitten" -/// } -/// }, -/// { -/// "type": "context", -/// "elements": [ -/// { -/// "type": "image", -/// "image_url": "https://platform.slack-edge.com/img/default_application_icon.png", -/// "alt_text": "footer icon" -/// }, -/// { -/// "type": "mrkdwn", -/// "text": "footer | " -/// } -/// ] -/// } -/// ] -/// }); -/// -/// let attachment_json = serde_json::to_value(attachment).unwrap(); -/// -/// assert_eq!(attachment_json, expected); -/// ``` -#[derive(Debug, Default, Clone, Serialize)] -pub struct Attachment { - #[serde(skip_serializing_if = "Vec::is_empty")] - blocks: Vec, - - #[serde(skip_serializing_if = "Option::is_none")] - color: Option, -} - -impl Attachment { - /// Constructs an Attachment. - /// - /// ```ignore - /// use slack_messaging::Attachment; - /// use serde_json::json; - /// - /// let attachment = Attachment::new(); - /// let expected = json!({}); - /// let attachment_json = serde_json::to_value(attachment).unwrap(); - /// - /// assert_eq!(attachment_json, expected); - /// ``` - pub fn new() -> Self { - Self::default() - } - - /// Sets color field. - /// - /// ```ignore - /// use slack_messaging::Attachment; - /// use serde_json::json; - /// - /// let attachment = Attachment::new().set_color("#FFFFFF"); - /// let expected = json!({ - /// "color": "#FFFFFF" - /// }); - /// let attachment_json = serde_json::to_value(attachment).unwrap(); - /// - /// assert_eq!(attachment_json, expected); - /// ``` - pub fn set_color>(self, color: T) -> Self { - Self { - color: Some(color.into()), - ..self - } - } - - /// Sets blocks field directly. The argument is a vector composed from any objects - /// that can transform into the enum [Block](crate::blocks::Block). - /// - /// ```ignore - /// use slack_messaging::Attachment; - /// use slack_messaging::blocks::{Context, Section}; - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; - /// - /// let attachment = Attachment::new() - /// .set_blocks( - /// vec![ - /// Context::new().push_element(Text::mrkdwn("*title*")).into(), - /// Section::new().set_text_mrkdwn("content").into() - /// ] - /// ); - /// - /// let expected = json!({ - /// "blocks": [ - /// { - /// "type": "context", - /// "elements": [ - /// { - /// "type": "mrkdwn", - /// "text": "*title*" - /// } - /// ] - /// }, - /// { - /// "type": "section", - /// "text": { - /// "type": "mrkdwn", - /// "text": "content" - /// } - /// } - /// ] - /// }); - /// - /// let attachment_json = serde_json::to_value(attachment).unwrap(); - /// - /// assert_eq!(attachment_json, expected); - /// ``` - pub fn set_blocks(self, blocks: Vec) -> Self { - Self { blocks, ..self } - } - - /// Adds an object to blocks field. The argument is an any object - /// that can transform into the enum [Block](crate::blocks::Block). - /// - /// ```ignore - /// use slack_messaging::Attachment; - /// use slack_messaging::blocks::{Context, Section}; - /// use slack_messaging::blocks::elements::Text; - /// use serde_json::json; - /// - /// let attachment = Attachment::new() - /// .push_block(Context::new().push_element(Text::mrkdwn("*title*"))) - /// .push_block(Section::new().set_text_mrkdwn("content")); - /// - /// let expected = json!({ - /// "blocks": [ - /// { - /// "type": "context", - /// "elements": [ - /// { - /// "type": "mrkdwn", - /// "text": "*title*" - /// } - /// ] - /// }, - /// { - /// "type": "section", - /// "text": { - /// "type": "mrkdwn", - /// "text": "content" - /// } - /// } - /// ] - /// }); - /// - /// let attachment_json = serde_json::to_value(attachment).unwrap(); - /// - /// assert_eq!(attachment_json, expected); - /// ``` - pub fn push_block>(self, block: T) -> Self { - let Self { mut blocks, .. } = self; - blocks.push(block.into()); - Self { blocks, ..self } - } -} diff --git a/src/blocks/actions.rs b/src/blocks/actions.rs index 25c6438..69351ca 100644 --- a/src/blocks/actions.rs +++ b/src/blocks/actions.rs @@ -1,8 +1,8 @@ use super::elements::{ - Button, CheckboxGroup, DatePicker, DatetimePicker, MultiSelectConversations, - MultiSelectExternals, MultiSelectPublicChannels, MultiSelectStaticOptions, MultiSelectUsers, - OverflowMenu, RadioButtonGroup, SelectConversations, SelectExternals, SelectPublicChannels, - SelectStaticOptions, SelectUsers, TimePicker, + Button, Checkboxes, DatePicker, DatetimePicker, MultiSelectConversations, MultiSelectExternals, + MultiSelectPublicChannels, MultiSelectStaticOptions, MultiSelectUsers, OverflowMenu, + RadioButtonGroup, SelectConversations, SelectExternals, SelectPublicChannels, + SelectStaticOptions, SelectUsers, TimePicker, WorkflowButton, }; use serde::Serialize; @@ -13,30 +13,35 @@ use serde::Serialize; /// /// The following is reproduction of [the 1st sample actions](https://api.slack.com/reference/block-kit/blocks#actions_examples). /// -/// ```ignore -/// use slack_messaging::blocks::Actions; -/// use slack_messaging::blocks::elements::{Button, SelectStaticOptions, Opt}; -/// use serde_json::json; -/// -/// let actions = Actions::new() -/// .set_block_id("actions1") -/// .push_element( -/// SelectStaticOptions::new() -/// .set_action_id("select_2") +/// ``` +/// # use slack_messaging::blocks::Actions; +/// # use slack_messaging::blocks::elements::{Button, SelectStaticOptions, Opt}; +/// let actions = Actions::builder() +/// .block_id("actions1") +/// .element( +/// SelectStaticOptions::builder() +/// .action_id("select_2") /// .placeholder("Which witch is the witchiest witch?") -/// .push_option(Opt::plain("Matilda").set_value("matilda")) -/// .push_option(Opt::plain("Glinda").set_value("glinda")) -/// .push_option(Opt::plain("Granny Weatherwax").set_value("grannyWeatherwax")) -/// .push_option(Opt::plain("Hermione").set_value("hermione")) +/// .set_options( +/// vec![ +/// Opt::builder().text("Matilda").value("matilda").build(), +/// Opt::builder().text("Glinda").value("glinda").build(), +/// Opt::builder().text("Granny Weatherwax").value("grannyWeatherwax").build(), +/// Opt::builder().text("Hermione").value("hermione").build(), +/// ] +/// ) +/// .build() /// ) -/// .push_element( -/// Button::new() -/// .set_action_id("button_1") -/// .set_value("cancel") +/// .element( +/// Button::builder() +/// .action_id("button_1") +/// .value("cancel") /// .text("Cancel") -/// ); +/// .build() +/// ) +/// .build(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "type": "actions", /// "block_id": "actions1", /// "elements": [ @@ -45,39 +50,34 @@ use serde::Serialize; /// "action_id": "select_2", /// "placeholder": { /// "type": "plain_text", -/// "text": "Which witch is the witchiest witch?", -/// "emoji": true +/// "text": "Which witch is the witchiest witch?" /// }, /// "options": [ /// { /// "text": { /// "type": "plain_text", -/// "text": "Matilda", -/// "emoji": true +/// "text": "Matilda" /// }, /// "value": "matilda" /// }, /// { /// "text": { /// "type": "plain_text", -/// "text": "Glinda", -/// "emoji": true +/// "text": "Glinda" /// }, /// "value": "glinda" /// }, /// { /// "text": { /// "type": "plain_text", -/// "text": "Granny Weatherwax", -/// "emoji": true +/// "text": "Granny Weatherwax" /// }, /// "value": "grannyWeatherwax" /// }, /// { /// "text": { /// "type": "plain_text", -/// "text": "Hermione", -/// "emoji": true +/// "text": "Hermione" /// }, /// "value": "hermione" /// } @@ -87,8 +87,7 @@ use serde::Serialize; /// "type": "button", /// "text": { /// "type": "plain_text", -/// "text": "Cancel", -/// "emoji": true +/// "text": "Cancel" /// }, /// "value": "cancel", /// "action_id": "button_1" @@ -96,43 +95,45 @@ use serde::Serialize; /// ] /// }); /// -/// let actions_json = serde_json::to_value(actions).unwrap(); +/// let json = serde_json::to_value(actions).unwrap(); /// -/// assert_eq!(actions_json, expected); +/// assert_eq!(json, expected); /// ``` /// /// And the following is the [2nd sample actions](https://api.slack.com/reference/block-kit/blocks#actions_examples). /// -/// ```ignore -/// use slack_messaging::blocks::Actions; -/// use slack_messaging::blocks::elements::{Button, DatePicker, Opt, OverflowMenu}; -/// use serde_json::json; -/// -/// let actions = Actions::new() -/// .set_block_id("actionblock789") -/// .push_element( -/// DatePicker::new() -/// .set_action_id("datepicker123") -/// .set_initial_date("1990-04-28") +/// ``` +/// # use slack_messaging::blocks::Actions; +/// # use slack_messaging::blocks::elements::{Button, DatePicker, Opt, OverflowMenu}; +/// let actions = Actions::builder() +/// .block_id("actionblock789") +/// .element( +/// DatePicker::builder() +/// .action_id("datepicker123") +/// .initial_date("1990-04-28") /// .placeholder("Select a date") +/// .build() /// ) -/// .push_element( -/// OverflowMenu::new() -/// .set_action_id("overflow") -/// .push_option(Opt::plain("*this is plain_text text*").set_value("value-0")) -/// .push_option(Opt::plain("*this is plain_text text*").set_value("value-1")) -/// .push_option(Opt::plain("*this is plain_text text*").set_value("value-2")) -/// .push_option(Opt::plain("*this is plain_text text*").set_value("value-3")) -/// .push_option(Opt::plain("*this is plain_text text*").set_value("value-4")) +/// .element( +/// OverflowMenu::builder() +/// .action_id("overflow") +/// .option(Opt::builder().text("*this is plain_text text*").value("value-0").build()) +/// .option(Opt::builder().text("*this is plain_text text*").value("value-1").build()) +/// .option(Opt::builder().text("*this is plain_text text*").value("value-2").build()) +/// .option(Opt::builder().text("*this is plain_text text*").value("value-3").build()) +/// .option(Opt::builder().text("*this is plain_text text*").value("value-4").build()) +/// .build() /// ) -/// .push_element( -/// Button::new() -/// .set_action_id("button") -/// .set_value("click_me_123") +/// .element( +/// Button::builder() +/// .action_id("button") +/// .value("click_me_123") /// .text("Click Me") -/// ); +/// .build() +/// ) +/// .build(); /// -/// let expected = json!({ +/// let expected = serde_json::json!({ /// "type": "actions", /// "block_id": "actionblock789", /// "elements": [ @@ -142,8 +143,7 @@ use serde::Serialize; /// "initial_date": "1990-04-28", /// "placeholder": { /// "type": "plain_text", -/// "text": "Select a date", -/// "emoji": true +/// "text": "Select a date" /// } /// }, /// { @@ -153,40 +153,35 @@ use serde::Serialize; /// { /// "text": { /// "type": "plain_text", -/// "text": "*this is plain_text text*", -/// "emoji": true +/// "text": "*this is plain_text text*" /// }, /// "value": "value-0" /// }, /// { /// "text": { /// "type": "plain_text", -/// "text": "*this is plain_text text*", -/// "emoji": true +/// "text": "*this is plain_text text*" /// }, /// "value": "value-1" /// }, /// { /// "text": { /// "type": "plain_text", -/// "text": "*this is plain_text text*", -/// "emoji": true +/// "text": "*this is plain_text text*" /// }, /// "value": "value-2" /// }, /// { /// "text": { /// "type": "plain_text", -/// "text": "*this is plain_text text*", -/// "emoji": true +/// "text": "*this is plain_text text*" /// }, /// "value": "value-3" /// }, /// { /// "text": { /// "type": "plain_text", -/// "text": "*this is plain_text text*", -/// "emoji": true +/// "text": "*this is plain_text text*" /// }, /// "value": "value-4" /// } @@ -196,8 +191,7 @@ use serde::Serialize; /// "type": "button", /// "text": { /// "type": "plain_text", -/// "text": "Click Me", -/// "emoji": true +/// "text": "Click Me" /// }, /// "value": "click_me_123", /// "action_id": "button" @@ -205,9 +199,9 @@ use serde::Serialize; /// ] /// }); /// -/// let actions_json = serde_json::to_value(actions).unwrap(); +/// let json = serde_json::to_value(actions).unwrap(); /// -/// assert_eq!(actions_json, expected); +/// assert_eq!(json, expected); /// ``` /// #[derive(Debug, Clone, Serialize)] @@ -221,64 +215,48 @@ pub struct Actions { block_id: Option, } -impl Default for Actions { - fn default() -> Self { - Self { - kind: "actions", - elements: vec![], - block_id: None, - } +impl Actions { + /// Construct a [`ActionsBuilder`]. + pub fn builder() -> ActionsBuilder { + ActionsBuilder::default() } } -impl Actions { - /// Constructs an Actions block. - /// - /// ```ignore - /// use slack_messaging::blocks::Actions; - /// use serde_json::json; - /// - /// let actions = Actions::new(); - /// - /// let expected = json!({ - /// "type": "actions", - /// "elements": [] - /// }); - /// - /// let actions_json = serde_json::to_value(actions).unwrap(); - /// - /// assert_eq!(actions_json, expected); - /// ``` - pub fn new() -> Self { - Self::default() - } +/// Builder for [`Actions`] object. +#[derive(Debug, Default)] +pub struct ActionsBuilder { + elements: Vec, + block_id: Option, +} - /// Sets elements field directly. The argument is a vector composed from any objects - /// that can transform into the enum [ActionsElement]. +impl ActionsBuilder { + /// Set elements field. The argument is a vector composed from any objects + /// that can transform into the enum [`ActionsElement`]. /// - /// ```ignore - /// use slack_messaging::blocks::Actions; - /// use slack_messaging::blocks::elements::{Button, SelectStaticOptions, Opt}; - /// use serde_json::json; - /// - /// let actions = Actions::new() + /// ``` + /// # use slack_messaging::blocks::Actions; + /// # use slack_messaging::blocks::elements::{Button, SelectStaticOptions, Opt}; + /// let actions = Actions::builder() /// .set_elements( /// vec![ - /// SelectStaticOptions::new() - /// .set_action_id("select_2") + /// SelectStaticOptions::builder() + /// .action_id("select_2") /// .placeholder("Which witch is the witchiest witch?") - /// .push_option(Opt::plain("Matilda").set_value("matilda")) - /// .push_option(Opt::plain("Glinda").set_value("glinda")) + /// .option(Opt::builder().text("Matilda").value("matilda").build()) + /// .option(Opt::builder().text("Glinda").value("glinda").build()) + /// .build() /// .into(), - /// Button::new() - /// .set_action_id("button_1") - /// .set_value("cancel") + /// Button::builder() + /// .action_id("button_1") + /// .value("cancel") /// .text("Cancel") + /// .build() /// .into(), /// ] - /// ); + /// ) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "actions", /// "elements": [ /// { @@ -286,23 +264,20 @@ impl Actions { /// "action_id": "select_2", /// "placeholder": { /// "type": "plain_text", - /// "text": "Which witch is the witchiest witch?", - /// "emoji": true + /// "text": "Which witch is the witchiest witch?" /// }, /// "options": [ /// { /// "text": { /// "type": "plain_text", - /// "text": "Matilda", - /// "emoji": true + /// "text": "Matilda" /// }, /// "value": "matilda" /// }, /// { /// "text": { /// "type": "plain_text", - /// "text": "Glinda", - /// "emoji": true + /// "text": "Glinda" /// }, /// "value": "glinda" /// } @@ -312,8 +287,7 @@ impl Actions { /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "Cancel", - /// "emoji": true + /// "text": "Cancel" /// }, /// "value": "cancel", /// "action_id": "button_1" @@ -321,37 +295,38 @@ impl Actions { /// ] /// }); /// - /// let actions_json = serde_json::to_value(actions).unwrap(); + /// let json = serde_json::to_value(actions).unwrap(); /// - /// assert_eq!(actions_json, expected); + /// assert_eq!(json, expected); /// ``` pub fn set_elements(self, elements: Vec) -> Self { Self { elements, ..self } } - /// Adds an object to elements field. The argument is an any object + /// Add an object to elements field. The argument is an any object /// that can transform into the enum [ActionsElement]. /// - /// ```ignore - /// use slack_messaging::blocks::Actions; - /// use slack_messaging::blocks::elements::{Button, DatePicker}; - /// use serde_json::json; - /// - /// let actions = Actions::new() - /// .push_element( - /// DatePicker::new() - /// .set_action_id("datepicker123") - /// .set_initial_date("1990-04-28") + /// ``` + /// # use slack_messaging::blocks::Actions; + /// # use slack_messaging::blocks::elements::{Button, DatePicker}; + /// let actions = Actions::builder() + /// .element( + /// DatePicker::builder() + /// .action_id("datepicker123") + /// .initial_date("1990-04-28") /// .placeholder("Select a date") + /// .build() /// ) - /// .push_element( - /// Button::new() - /// .set_action_id("button") - /// .set_value("click_me_123") + /// .element( + /// Button::builder() + /// .action_id("button") + /// .value("click_me_123") /// .text("Click Me") - /// ); + /// .build() + /// ) + /// .build(); /// - /// let expected = json!({ + /// let expected = serde_json::json!({ /// "type": "actions", /// "elements": [ /// { @@ -360,16 +335,14 @@ impl Actions { /// "initial_date": "1990-04-28", /// "placeholder": { /// "type": "plain_text", - /// "text": "Select a date", - /// "emoji": true + /// "text": "Select a date" /// } /// }, /// { /// "type": "button", /// "text": { /// "type": "plain_text", - /// "text": "Click Me", - /// "emoji": true + /// "text": "Click Me" /// }, /// "value": "click_me_123", /// "action_id": "button" @@ -377,38 +350,66 @@ impl Actions { /// ] /// }); /// - /// let actions_json = serde_json::to_value(actions).unwrap(); + /// let json = serde_json::to_value(actions).unwrap(); /// - /// assert_eq!(actions_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn push_element>(self, element: T) -> Self { + pub fn element(self, element: impl Into) -> Self { let mut elements = self.elements; elements.push(element.into()); Self { elements, ..self } } - /// Sets block_id field. + /// Set block_id field. + /// + /// ``` + /// # use slack_messaging::blocks::Actions; + /// let actions = Actions::builder() + /// .set_block_id(Some("actions_block_1".into())) + /// .build(); + /// + /// let expected = serde_json::json!({ + /// "type": "actions", + /// "elements": [], + /// "block_id": "actions_block_1" + /// }); /// - /// ```ignore - /// use slack_messaging::blocks::Actions; - /// use serde_json::json; + /// let json = serde_json::to_value(actions).unwrap(); /// - /// let actions = Actions::new().set_block_id("actions_block_1"); + /// assert_eq!(json, expected); + /// ``` + pub fn set_block_id(self, block_id: Option) -> Self { + Self { block_id, ..self } + } + + /// Set block_id field. /// - /// let expected = json!({ + /// ``` + /// # use slack_messaging::blocks::Actions; + /// let actions = Actions::builder() + /// .block_id("actions_block_1") + /// .build(); + /// + /// let expected = serde_json::json!({ /// "type": "actions", /// "elements": [], /// "block_id": "actions_block_1" /// }); /// - /// let actions_json = serde_json::to_value(actions).unwrap(); + /// let json = serde_json::to_value(actions).unwrap(); /// - /// assert_eq!(actions_json, expected); + /// assert_eq!(json, expected); /// ``` - pub fn set_block_id>(self, block_id: T) -> Self { - Self { - block_id: Some(block_id.into()), - ..self + pub fn block_id(self, block_id: impl Into) -> Self { + self.set_block_id(Some(block_id.into())) + } + + /// Build an [`Actions`] object. + pub fn build(self) -> Actions { + Actions { + kind: "actions", + elements: self.elements, + block_id: self.block_id, } } } @@ -423,7 +424,7 @@ pub enum ActionsElement { /// [Checkbox group](https://api.slack.com/reference/block-kit/block-elements#checkboxes) /// representation - CheckboxGroup(Box), + Checkboxes(Box), /// [Date picker element](https://api.slack.com/reference/block-kit/block-elements#datepicker) /// representation @@ -484,106 +485,41 @@ pub enum ActionsElement { /// [Time picker element](https://api.slack.com/reference/block-kit/block-elements#timepicker) /// representation TimePicker(Box), -} -impl From