use serde::{Deserialize, Serialize};
use crate::card::{components::CardElement, href::FeishuCardHrefVal};
#[derive(Debug, Serialize, Deserialize)]
pub struct ColumnSetContainer {
tag: String,
#[serde(skip_serializing_if = "Option::is_none")]
horizontal_spacing: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
horizontal_align: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
margin: Option<String>,
flex_mode: String,
#[serde(skip_serializing_if = "Option::is_none")]
background_style: Option<String>,
columns: Vec<Column>,
#[serde(skip_serializing_if = "Option::is_none")]
action: Option<ColumnAction>,
}
impl Default for ColumnSetContainer {
fn default() -> Self {
ColumnSetContainer {
tag: "column_set".to_string(),
background_style: None,
horizontal_spacing: None,
horizontal_align: None,
columns: vec![],
margin: None,
flex_mode: "".to_string(),
action: None,
}
}
}
impl ColumnSetContainer {
pub fn new() -> Self {
ColumnSetContainer::default()
}
pub fn horizontal_spacing(mut self, horizontal_spacing: impl ToString) -> Self {
self.horizontal_spacing = Some(horizontal_spacing.to_string());
self
}
pub fn horizontal_align(mut self, horizontal_align: impl ToString) -> Self {
self.horizontal_align = Some(horizontal_align.to_string());
self
}
pub fn margin(mut self, margin: impl ToString) -> Self {
self.margin = Some(margin.to_string());
self
}
pub fn flex_mode(mut self, flex_mode: impl ToString) -> Self {
self.flex_mode = flex_mode.to_string();
self
}
pub fn background_style(mut self, background_style: impl ToString) -> Self {
self.background_style = Some(background_style.to_string());
self
}
pub fn columns(mut self, columns: Vec<Column>) -> Self {
self.columns = columns;
self
}
pub fn action(mut self, action: ColumnAction) -> Self {
self.action = Some(action);
self
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Column {
tag: String,
#[serde(skip_serializing_if = "Option::is_none")]
background_style: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
width: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
weight: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
vertical_align: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
vertical_spacing: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
padding: Option<String>,
elements: Vec<CardElement>,
#[serde(skip_serializing_if = "Option::is_none")]
action: Option<ColumnAction>,
}
impl Default for Column {
fn default() -> Self {
Column {
tag: "column".to_string(),
background_style: None,
width: None,
weight: None,
vertical_align: None,
vertical_spacing: None,
padding: None,
elements: vec![],
action: None,
}
}
}
impl Column {
pub fn new() -> Self {
Self::default()
}
pub fn background_style(mut self, background_style: impl ToString) -> Self {
self.background_style = Some(background_style.to_string());
self
}
pub fn width(mut self, width: impl ToString) -> Self {
self.width = Some(width.to_string());
self
}
pub fn weight(mut self, weight: u32) -> Self {
self.weight = Some(weight);
self
}
pub fn vertical_align(mut self, vertical_align: impl ToString) -> Self {
self.vertical_align = Some(vertical_align.to_string());
self
}
pub fn vertical_spacing(mut self, vertical_spacing: impl ToString) -> Self {
self.vertical_spacing = Some(vertical_spacing.to_string());
self
}
pub fn padding(mut self, padding: impl ToString) -> Self {
self.padding = Some(padding.to_string());
self
}
pub fn elements(mut self, elements: Vec<CardElement>) -> Self {
self.elements = elements;
self
}
pub fn action(mut self, action: ColumnAction) -> Self {
self.action = Some(action);
self
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ColumnAction {
#[serde(skip_serializing_if = "Option::is_none")]
multi_url: Option<FeishuCardHrefVal>,
}
impl ColumnAction {
pub fn new() -> Self {
Self::default()
}
pub fn multi_url(mut self, multi_url: FeishuCardHrefVal) -> Self {
self.multi_url = Some(multi_url);
self
}
}
#[cfg(test)]
mod test {
use serde_json::json;
use crate::card::{
components::containers::column_set::{Column, ColumnAction, ColumnSetContainer},
href::FeishuCardHrefVal,
};
#[test]
fn test_column_set() {
let column_set = ColumnSetContainer::new()
.horizontal_spacing("large")
.horizontal_align("left")
.margin("0px")
.flex_mode("none")
.background_style("default")
.action(
ColumnAction::new().multi_url(
FeishuCardHrefVal::new()
.url("https://open.feishu.cn")
.pc_url("https://open.feishu.com")
.ios_url("https://developer.apple.com/")
.android_url("https://developer.android.com/"),
),
)
.columns(vec![Column::new()
.background_style("default")
.width("auto")
.weight(1)
.vertical_align("center")
.vertical_spacing("4px")
.padding("8px")
.action(
ColumnAction::new().multi_url(
FeishuCardHrefVal::new()
.url("https://www.baidu.com")
.pc_url("https://www.baidu.com")
.ios_url("https://www.google.com")
.android_url("https://www.apple.com.cn"),
),
)]);
let expect = json!({
"tag": "column_set", "horizontal_spacing": "large", "horizontal_align": "left", "margin": "0px", "flex_mode": "none", "background_style": "default", "action": { "multi_url": {
"url": "https://open.feishu.cn",
"pc_url": "https://open.feishu.com",
"ios_url": "https://developer.apple.com/",
"android_url": "https://developer.android.com/"
}
},
"columns": [
{
"tag": "column",
"background_style": "default", "width": "auto", "weight": 1, "vertical_align": "center", "vertical_spacing": "4px", "padding": "8px", "action": {
"multi_url": {
"url": "https://www.baidu.com",
"pc_url": "https://www.baidu.com",
"ios_url": "https://www.google.com",
"android_url": "https://www.apple.com.cn"
}
},
"elements": [] }
]
});
assert_eq!(json!(column_set), expect);
}
}