use crate::store::model::FieldKind; use serde_json::Value; use std::borrow::Cow; use crate::store::{model, Indexes}; use lazy_static::lazy_static; lazy_static! { /// This is an example for using doc comment attributes static ref EMPTY_VEC: Vec = vec![]; } #[derive(Serialize, Debug, Default)] pub struct RenderedField<'a> { pub key: Cow<'a, str>, pub label: Cow<'a, str>, pub kind: &'static str, pub step: &'static str, pub min: String, pub max: String, pub all_tags_json: String, pub tags_json: String, pub options: Option<&'a Vec>, pub value: Cow<'a, str>, pub checked: bool, } impl<'a> RenderedField<'a> { pub fn from_template_field<'i>( key: &'i String, field: &'i model::Field, value: Option<&'i Value>, index: &'i Indexes ) -> RenderedField<'i> { let mut rendered = RenderedField::default(); rendered.key = key.as_str().into(); rendered.label = if field.label.is_empty() { titlecase::titlecase(&key.replace('_', " ")).into() } else { field.label.as_str().into() }; match &field.kind { FieldKind::String => { rendered.kind = "string"; if let Some(Value::String(s)) = value { rendered.value = Cow::Borrowed(&s.as_str()); } } FieldKind::Text => { rendered.kind = "text"; if let Some(Value::String(s)) = value { rendered.value = Cow::Borrowed(&s.as_str()); } } FieldKind::Bool { default } => { rendered.kind = "bool"; rendered.checked = if let Some(Value::Bool(v)) = value { *v } else { *default } } FieldKind::Int { min, max, default } => { rendered.kind = "number"; let num = if let Some(Value::Number(n)) = value { n.as_i64().expect("Error parsing number") } else { *default }; if let Some(n) = min { rendered.min = n.to_string(); } if let Some(n) = max { rendered.max = n.to_string(); } rendered.value = Cow::Owned(num.to_string()); rendered.step = "1"; } FieldKind::Float { min, max, default } => { rendered.kind = "number"; let num = if let Some(Value::Number(n)) = value { n.as_f64().expect("Error parsing number") } else { *default }; if let Some(n) = min { rendered.min = n.to_string(); } if let Some(n) = max { rendered.max = n.to_string(); } rendered.value = Cow::Owned(num.to_string()); rendered.step = "any"; } FieldKind::Enum { options, default } => { rendered.kind = "select"; rendered.options = Some(options); if let Some(Value::String(s)) = value { rendered.value = Cow::Borrowed(&s.as_str()); } } FieldKind::FreeEnum { enum_group } => { rendered.kind = "free_select"; let group = enum_group.as_ref().unwrap_or(key); let options = index.free_enums.get(group).unwrap_or(&EMPTY_VEC); rendered.options = Some(options); if let Some(Value::String(s)) = value { rendered.value = Cow::Borrowed(&s.as_str()); } } FieldKind::Tags { options } => { rendered.kind = "tags"; rendered.options = Some(options); if value.is_some() { rendered.value = serde_json::from_value::>(value.unwrap().clone()) .unwrap().join(" ").into(); } if let Some(Value::Array(items)) = value { rendered.tags_json = serde_json::to_string(items).unwrap(); } else { rendered.tags_json = "[]".into(); }; rendered.all_tags_json = serde_json::to_string(options).unwrap(); } FieldKind::FreeTags { tag_group } => { rendered.kind = "free_tags"; let group = tag_group.as_ref().unwrap_or(key); let options = index.free_tags.get(group).unwrap_or(&EMPTY_VEC); if value.is_some() { rendered.value = serde_json::from_value::>(value.unwrap().clone()) .unwrap().join(" ").into(); } if let Some(Value::Array(items)) = value { rendered.tags_json = serde_json::to_string(items).unwrap(); } else { rendered.tags_json = "[]".into(); }; rendered.options = Some(options); rendered.tags_json = serde_json::to_string(options).unwrap(); } } rendered } }