use std::iter::zip; use interim_models::presentation::{ DropdownOption, Presentation, PresentationDiscriminants, RFC_3339_S, TextInputMode, }; use serde::Deserialize; use crate::errors::AppError; /// A subset of an HTTP form that represents a [`Presentation`] in its component /// parts. It may be merged into a larger HTTP form using `serde(flatten)`. #[derive(Clone, Debug, Deserialize)] pub(crate) struct PresentationForm { pub(crate) presentation_tag: String, #[serde(default)] pub(crate) dropdown_option_colors: Vec, #[serde(default)] pub(crate) dropdown_option_values: Vec, #[serde(default)] pub(crate) text_input_mode: String, #[serde(default)] pub(crate) timestamp_format: String, } impl TryFrom for Presentation { type Error = AppError; fn try_from(form_value: PresentationForm) -> Result { let discriminant = PresentationDiscriminants::try_from(form_value.presentation_tag.as_str())?; Ok(match discriminant { PresentationDiscriminants::Dropdown => Presentation::Dropdown { allow_custom: false, options: zip( form_value.dropdown_option_colors, form_value.dropdown_option_values, ) .map(|(color, value)| DropdownOption { color, value }) .collect(), }, PresentationDiscriminants::Numeric => Presentation::Numeric {}, PresentationDiscriminants::Text => Presentation::Text { input_mode: TextInputMode::try_from(form_value.text_input_mode.as_str())?, }, PresentationDiscriminants::Timestamp => Presentation::Timestamp { format: if form_value.timestamp_format.is_empty() { RFC_3339_S.to_owned() } else { form_value.timestamp_format }, utc: true, }, PresentationDiscriminants::Uuid => Presentation::Uuid {}, }) } }