phonograph/phono-models/src/presentation.rs
2025-11-19 02:14:43 +00:00

96 lines
2.6 KiB
Rust

use phono_backends::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<DropdownOption>,
},
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<Self> {
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 {}
}
}