use crate::errors::ParserError;
#[cfg(feature = "schema")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fs::File, io::BufReader};
fn default_input_err_msg() -> String {
"This field is required, please enter a value.".to_string()
}
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum Config {
Root {
languages: HashMap<String, String>,
},
Language {
#[serde(default = "default_input_err_msg")]
input_err_msg: String,
workflows: HashMap<String, Workflow>,
},
}
impl Config {
pub fn new(filename: &str) -> Result<Self, ParserError> {
let file = File::open(filename).map_err(|err| ParserError::FsError {
filename: filename.to_string(),
source: err,
})?;
let reader = BufReader::new(file);
let contents: Self =
serde_yaml::from_reader(reader).map_err(|err| ParserError::ParseRawError {
filename: filename.to_string(),
source: err,
})?;
Ok(contents)
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
pub struct Workflow {
pub title: String,
pub sections: HashMap<String, Section>,
pub index: String,
pub endpoints: HashMap<String, Endpoint>,
}
pub type Section = Vec<SectionElem>;
#[derive(Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(untagged)]
pub enum SectionElem {
Text(String),
Progression {
text: String,
link: String,
tags: Vec<String>,
},
Input(InputSectionElem),
}
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct InputSectionElem {
pub id: String,
pub label: String,
#[serde(default)]
pub optional: bool,
pub default: Option<String>,
#[serde(flatten)]
pub input: Input,
}
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum Input {
Text {
#[serde(flatten)]
input_type: InputType,
},
Select {
options: Vec<SelectOption>,
#[serde(default)]
can_select_multiple: bool,
},
}
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "type")]
#[serde(rename_all = "kebab-case")]
pub enum InputType {
Boolean {
tags: Option<Vec<String>>,
},
Multiline,
Color,
Text,
Date,
DatetimeLocal,
Email,
Month,
Number {
#[serde(default)]
min: Option<i32>,
#[serde(default)]
max: Option<i32>,
},
Password,
Range {
min: i32,
max: i32,
},
Tel,
Time,
Url,
Week,
}
impl Default for InputType {
fn default() -> Self {
Self::Text
}
}
impl ToString for InputType {
fn to_string(&self) -> String {
match self {
Self::Boolean { .. } => "checkbox".to_string(),
Self::Multiline => "multiline".to_string(),
Self::Color => "color".to_string(),
Self::Text => "text".to_string(),
Self::Date => "date".to_string(),
Self::DatetimeLocal => "datetime-local".to_string(),
Self::Email => "email".to_string(),
Self::Month => "month".to_string(),
Self::Number { .. } => "number".to_string(),
Self::Password => "password".to_string(),
Self::Range { .. } => "range".to_string(),
Self::Tel => "tel".to_string(),
Self::Time => "time".to_string(),
Self::Url => "url".to_string(),
Self::Week => "week".to_string(),
}
}
}
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum SelectOption {
Simple(String),
WithTags {
text: String,
tags: Vec<String>,
},
}
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum Endpoint {
Report {
preamble: String,
text: String,
dest_text: String,
dest_url: String,
},
Instructional(String),
}