use std::borrow::Cow;
use serde::{Deserialize, Serialize};
#[cfg(feature = "validation")]
use validator::Validate;
#[cfg(feature = "validation")]
use crate::val_helpr::ValidationResult;
use crate::{compose::text,
convert,
elems,
elems::{select, BlockElement}};
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
#[cfg_attr(feature = "validation", derive(Validate))]
pub struct Input<'a> {
#[cfg_attr(feature = "validation", validate(custom = "validate::label"))]
label: text::Text,
element: SupportedElement<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation",
validate(custom = "super::validate_block_id"))]
block_id: Option<Cow<'a, str>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "validation", validate(custom = "validate::hint"))]
hint: Option<text::Text>,
#[serde(skip_serializing_if = "Option::is_none")]
dispatch_action: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
optional: Option<bool>,
}
impl<'a> Input<'a> {
pub fn builder() -> build::InputBuilderInit<'a> {
build::InputBuilderInit::new()
}
#[cfg(feature = "validation")]
#[cfg_attr(docsrs, doc(cfg(feature = "validation")))]
pub fn validate(&self) -> ValidationResult {
Validate::validate(self)
}
}
pub mod build {
use std::marker::PhantomData;
use super::*;
use crate::build::*;
#[allow(non_camel_case_types)]
pub mod method {
#[derive(Clone, Copy, Debug)]
pub struct element;
#[derive(Clone, Copy, Debug)]
pub struct label;
}
pub type InputBuilderInit<'a> =
InputBuilder<'a,
RequiredMethodNotCalled<method::element>,
RequiredMethodNotCalled<method::label>>;
#[derive(Debug)]
pub struct InputBuilder<'a, Element, Label> {
label: Option<text::Text>,
element: Option<SupportedElement<'a>>,
hint: Option<text::Text>,
block_id: Option<Cow<'a, str>>,
optional: Option<bool>,
dispatch_action: Option<bool>,
state: PhantomData<(Element, Label)>,
}
impl<'a, E, L> InputBuilder<'a, E, L> {
pub fn new() -> Self {
Self { label: None,
element: None,
hint: None,
block_id: None,
optional: None,
dispatch_action: None,
state: PhantomData::<_> }
}
pub fn label<T>(self, label: T) -> InputBuilder<'a, E, Set<method::label>>
where T: Into<text::Plain>
{
InputBuilder { label: Some(label.into().into()),
element: self.element,
hint: self.hint,
block_id: self.block_id,
optional: self.optional,
dispatch_action: self.dispatch_action,
state: PhantomData::<_> }
}
pub fn block_id<S>(mut self, block_id: S) -> Self
where S: Into<Cow<'a, str>>
{
self.block_id = Some(block_id.into());
self
}
pub fn dispatch_actions(mut self, should: bool) -> Self {
self.dispatch_action = Some(should);
self
}
pub fn optional(mut self, optional: bool) -> Self {
self.optional = Some(optional);
self
}
pub fn hint<T>(mut self, hint: T) -> Self
where T: Into<text::Plain>
{
self.hint = Some(hint.into().into());
self
}
}
impl<'a, L> InputBuilder<'a, RequiredMethodNotCalled<method::element>, L> {
pub fn element<El>(self,
element: El)
-> InputBuilder<'a, Set<method::element>, L>
where El: Into<SupportedElement<'a>>
{
InputBuilder { label: self.label,
element: Some(element.into()),
hint: self.hint,
block_id: self.block_id,
optional: self.optional,
dispatch_action: self.dispatch_action,
state: PhantomData::<_> }
}
#[cfg(feature = "blox")]
#[cfg_attr(docsrs, doc(cfg(feature = "blox")))]
pub fn child<El>(self,
element: El)
-> InputBuilder<'a, Set<method::element>, L>
where El: Into<SupportedElement<'a>>
{
self.element(element)
}
}
impl<'a> InputBuilder<'a, Set<method::element>, Set<method::label>> {
pub fn build(self) -> Input<'a> {
Input { element: self.element.unwrap(),
label: self.label.unwrap(),
hint: self.hint,
dispatch_action: self.dispatch_action,
optional: self.optional,
block_id: self.block_id }
}
}
}
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, Serialize)]
pub struct SupportedElement<'a>(BlockElement<'a>);
convert!(impl<'a> From<elems::Radio<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<elems::TextInput<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<elems::Checkboxes<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<elems::DatePicker<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::Static<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::External<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::User<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::Conversation<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::PublicChannel<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::multi::Static<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::multi::External<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::multi::User<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::multi::Conversation<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
convert!(impl<'a> From<select::multi::PublicChannel<'a>> for SupportedElement<'a> => |r| SupportedElement(BlockElement::from(r)));
#[cfg(feature = "validation")]
mod validate {
use crate::{compose::text,
val_helpr::{below_len, ValidatorResult}};
pub(super) fn label(text: &text::Text) -> ValidatorResult {
below_len("Input Label", 2000, text.as_ref())
}
pub(super) fn hint(text: &text::Text) -> ValidatorResult {
below_len("Input Hint", 2000, text.as_ref())
}
}