use serde::{Deserialize, Serialize};
use serde_json::{json, Map, Value};
#[derive(Deserialize, Serialize, Debug)]
pub struct Record {
#[serde(rename = "recordId")]
pub record_id: String,
pub fields: Value,
#[serde(rename = "createdAt")]
pub created_at: u64,
#[serde(rename = "updatedAt")]
pub updated_at: u64,
}
#[derive(Deserialize, Serialize, Debug)]
pub struct GetRecordsResp {
#[serde(rename = "pageNum")]
pub page_num: u32,
pub records: Vec<Record>,
#[serde(rename = "pageSize")]
pub page_size: u32,
pub total: u32,
}
#[derive(Deserialize, Serialize)]
pub struct GetRecordsReq {
field: Map<String, Value>,
}
impl GetRecordsReq {
pub fn builder() -> GetRecordsReqBuilder {
GetRecordsReqBuilder { field: Map::new() }
}
pub fn to_parameter_vec(self) -> Vec<(String, String)> {
let mut result: Vec<(String, String)> = Vec::new();
for (key, value) in self.field {
if key.eq("recordIds") {
let record_ids = value.as_array().unwrap();
for record_id in record_ids {
result.push((key.clone(), record_id.as_str().unwrap().to_string()))
}
} else if key.eq("fields") {
let fields = value.as_array().unwrap();
for field in fields {
result.push((
String::from("fields[]"),
field.as_str().unwrap().to_string(),
))
}
} else if key.eq("sort") {
let sorts = value.as_array().unwrap();
for sort in sorts {
result.push((
format!("sort[][field]",),
sort[0].as_str().unwrap().to_string(),
));
result.push((
format!("sort[][order]",),
sort[1].as_str().unwrap().to_string(),
));
}
} else if key.eq("pageSize") || key.eq("maxRecords") || key.eq("pageNum") {
result.push((key, value.as_u64().unwrap().to_string()));
} else {
result.push((key, String::from(value.as_str().unwrap())));
}
}
result
}
}
pub struct GetRecordsReqBuilder {
field: Map<String, Value>,
}
impl GetRecordsReqBuilder {
pub fn page_size(mut self, page_size: u64) -> GetRecordsReqBuilder {
self.field
.insert(String::from("pageSize"), json!(page_size));
self
}
pub fn max_records(mut self, max_records: u64) -> GetRecordsReqBuilder {
self.field
.insert(String::from("maxRecords"), json!(max_records));
self
}
pub fn page_num(mut self, page_num: u64) -> GetRecordsReqBuilder {
self.field.insert(String::from("pageNum"), json!(page_num));
self
}
pub fn sort(mut self, sort: Vec<(String, Sort)>) -> GetRecordsReqBuilder {
let mut sort_value: Vec<(String, String)> = Vec::new();
for s in sort {
match s.1 {
Sort::ASC => sort_value.push((s.0, "asc".to_string())),
Sort::DESC => sort_value.push((s.0, "desc".to_string())),
}
}
self.field.insert(String::from("sort"), json!(sort_value));
self
}
pub fn record_ids(mut self, record_ids: Vec<String>) -> GetRecordsReqBuilder {
self.field
.insert(String::from("recordIds"), json!(record_ids));
self
}
pub fn view_id(mut self, view_id: String) -> GetRecordsReqBuilder {
self.field.insert(String::from("viewId"), json!(view_id));
self
}
pub fn fields(mut self, fields: Vec<String>) -> GetRecordsReqBuilder {
self.field.insert(String::from("fields"), json!(fields));
self
}
pub fn filter_by_formula(mut self, filter_by_formula: String) -> GetRecordsReqBuilder {
self.field
.insert(String::from("filterByFormula"), json!(filter_by_formula));
self
}
pub fn cell_format(mut self, cell_format: String) -> GetRecordsReqBuilder {
self.field
.insert(String::from("cellFormat"), json!(cell_format));
self
}
pub fn field_key(mut self, field_key: FieldID) -> GetRecordsReqBuilder {
match field_key {
FieldID::ID => {
self.field.insert(String::from("fieldKey"), json!("id"));
}
FieldID::NAME => {
self.field.insert(String::from("fieldKey"), json!("name"));
}
}
self
}
pub fn build(self) -> GetRecordsReq {
GetRecordsReq { field: self.field }
}
}
pub type PatchRecordsReq = PostRecordsReq;
#[derive(Deserialize, Serialize, Debug)]
pub struct PostRecordsReq {
#[serde(rename = "fieldKey")]
field_key: String,
records: Vec<RecordMap>,
}
impl PostRecordsReq {
pub fn builder() -> PostRecordsReqBuilder {
PostRecordsReqBuilder::new()
}
pub fn to_json_string(self) -> String {
let mut value: Map<String, Value> = Map::new();
value.insert("fieldKey".to_string(), Value::String(self.field_key));
let mut record_values: Vec<Value> = Vec::new();
for record in self.records {
let record_value_string = serde_json::to_string(&record).unwrap();
let record_value: Value = serde_json::from_str(&record_value_string).unwrap();
record_values.push(record_value);
}
value.insert("records".to_string(), Value::Array(record_values));
serde_json::to_string(&value).unwrap()
}
}
pub struct PostRecordsReqBuilder {
field_key: String,
records: Vec<RecordMap>,
}
impl PostRecordsReqBuilder {
pub fn new() -> PostRecordsReqBuilder {
PostRecordsReqBuilder {
field_key: String::from("name"),
records: Vec::new(),
}
}
pub fn field_key(self, field_key: FieldID) -> PostRecordsReqBuilder {
let field_key_value;
match field_key {
FieldID::ID => field_key_value = "id".to_string(),
FieldID::NAME => field_key_value = "name".to_string(),
}
PostRecordsReqBuilder {
field_key: field_key_value,
..self
}
}
pub fn records(self, records: Vec<RecordMap>) -> PostRecordsReqBuilder {
PostRecordsReqBuilder { records, ..self }
}
pub fn build(self) -> PostRecordsReq {
PostRecordsReq {
field_key: self.field_key,
records: self.records,
}
}
}
#[derive(Deserialize, Serialize, Debug)]
pub struct RecordMap {
#[serde(rename = "recordId")]
record_id: String,
fields: Map<String, Value>,
}
impl RecordMap {
pub fn builder() -> RecordMapBuilder {
RecordMapBuilder {
record_id: "".to_string(),
fields: Map::new(),
}
}
}
pub struct RecordMapBuilder {
pub record_id: String,
pub fields: Map<String, Value>,
}
impl RecordMapBuilder {
pub fn record_id(mut self, record_id: String) -> RecordMapBuilder {
self.record_id = record_id;
self
}
pub fn put_string(mut self, field_key: &String, field_value: String) -> RecordMapBuilder {
self.fields
.insert(field_key.clone(), Value::String(field_value));
self
}
pub fn put_strings(
mut self,
field_key: &String,
field_values: Vec<String>,
) -> RecordMapBuilder {
let mut values: Vec<Value> = Vec::new();
for field_value in field_values {
values.push(Value::String(field_value));
}
self.fields.insert(field_key.clone(), Value::Array(values));
self
}
pub fn build(self) -> RecordMap {
RecordMap {
record_id: self.record_id,
fields: self.fields,
}
}
}
pub type PatchRecordsResp = PostRecordsResp;
#[derive(Deserialize, Serialize, Debug)]
pub struct PostRecordsResp {
pub records: Vec<Record>,
}
pub enum Sort {
ASC,
DESC,
}
pub enum FieldID {
ID,
NAME,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_records_req() {
let get_records_req = GetRecordsReq::builder()
.page_size(1)
.max_records(1)
.page_num(1)
.sort(vec![
("1".to_string(), Sort::ASC),
("2".to_string(), Sort::DESC),
])
.record_ids(vec!["1".to_string(), "2".to_string()])
.view_id("1".to_string())
.fields(vec!["1".to_string(), "2".to_string()])
.filter_by_formula("1".to_string())
.cell_format("1".to_string())
.field_key(FieldID::ID)
.build();
println!("{:?}", get_records_req.to_parameter_vec())
}
#[test]
fn post_records_req() {
let record1 = RecordMap::builder()
.put_string(&"field_key1".to_string(), "field_value1".to_string())
.put_string(&"field_key2".to_string(), "field_value2".to_string())
.build();
let record2 = RecordMap::builder()
.put_string(&"field_key1".to_string(), "field_value1".to_string())
.put_string(&"field_key2".to_string(), "field_value2".to_string())
.build();
let req = PostRecordsReq {
field_key: "name".to_string(),
records: vec![record1, record2],
};
assert_eq!(
r#"{"fieldKey":"name","records":[{"fields":{"field_key1":"field_value1","field_key2":"field_value2"},"recordId":""},{"fields":{"field_key1":"field_value1","field_key2":"field_value2"},"recordId":""}]}"#,
req.to_json_string()
)
}
#[test]
fn patch_records_req() {
let record1 = RecordMap::builder()
.record_id("rec1".to_string())
.put_string(&"field_key1".to_string(), "field_value1".to_string())
.put_string(&"field_key2".to_string(), "field_value2".to_string())
.build();
let record2 = RecordMap::builder()
.record_id("rec1".to_string())
.put_string(&"field_key1".to_string(), "field_value1".to_string())
.put_string(&"field_key2".to_string(), "field_value2".to_string())
.build();
let req = PostRecordsReq {
field_key: "name".to_string(),
records: vec![record1, record2],
};
assert_eq!(
r#"{"fieldKey":"name","records":[{"fields":{"field_key1":"field_value1","field_key2":"field_value2"},"recordId":"rec1"},{"fields":{"field_key1":"field_value1","field_key2":"field_value2"},"recordId":"rec1"}]}"#,
req.to_json_string()
)
}
}