use interim_pgtypes::pg_attribute::PgAttribute; use serde::{Deserialize, Serialize}; use strum::{EnumDiscriminants, EnumIter, EnumString}; pub const RFC_3339_S: &str = "yyyy-MM-dd'T'HH:mm:ssXXX"; /// Struct defining how a field's is displayed and how it accepts input in UI. #[derive( Clone, Debug, Deserialize, EnumDiscriminants, EnumIter, EnumString, PartialEq, Serialize, strum::Display, )] #[strum_discriminants(derive(EnumString))] #[serde(tag = "t", content = "c")] pub enum Presentation { Dropdown { allow_custom: bool, options: Vec, }, Numeric {}, Text { input_mode: TextInputMode, }, Timestamp { format: String, utc: bool, }, Uuid {}, } #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub struct DropdownOption { pub color: String, pub value: String, } impl Presentation { /// Returns a SQL fragment for the default data type for creating or /// altering a backing column, such as "integer", or "timestamptz". pub fn attr_data_type_fragment(&self) -> &'static str { match self { Self::Dropdown { .. } | Self::Text { .. } => "text", Self::Numeric { .. } => "numeric", Self::Timestamp { .. } => "timestamptz", Self::Uuid { .. } => "uuid", } } /// Generate the default presentation based on an existing column's type. /// Returns None if no default presentation exists. pub fn default_from_attr(attr: &PgAttribute) -> Option { match attr.regtype.to_lowercase().as_str() { "numeric" => Some(Self::Numeric {}), "text" => Some(Self::Text { input_mode: TextInputMode::MultiLine {}, }), "timestamp" => Some(Self::Timestamp { format: RFC_3339_S.to_owned(), utc: true, }), "uuid" => Some(Self::Uuid {}), _ => None, } } } impl Default for Presentation { /// Defaults to [`Self::Text`] as a reasonable fallback. The [`Default`] /// trait is implemented for convenience, but in the vast majority of cases /// the presentation value should be well defined and this should not be /// called directly. fn default() -> Self { Self::Text { input_mode: Default::default(), } } } #[derive(Clone, Debug, Deserialize, EnumString, EnumIter, PartialEq, Serialize, strum::Display)] #[serde(tag = "t", content = "c")] pub enum TextInputMode { SingleLine {}, MultiLine {}, } impl Default for TextInputMode { fn default() -> Self { Self::MultiLine {} } }