n5i 0.12.0-dev.1

Common components for n5i
Documentation
use serde::{Deserialize, Serialize};

use crate::utils::{MultiLanguageItem, true_default};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "graphql", derive(async_graphql::SimpleObject))]
pub struct EnumOption {
    pub value: String,
    pub display_name: MultiLanguageItem,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(untagged)]
pub enum EnumOptionRepresentation {
    String(String),
    Detailed(EnumOption),
}

#[cfg(feature = "graphql")]
impl async_graphql::resolver_utils::ContainerType for EnumOptionRepresentation {
    async fn resolve_field(
        &self,
        ctx: &async_graphql::Context<'_>,
    ) -> async_graphql::ServerResult<Option<async_graphql::Value>> {
        self.as_detailed().resolve_field(ctx).await
    }
}
#[cfg(feature = "graphql")]
impl async_graphql::OutputType for EnumOptionRepresentation {
    fn type_name() -> std::borrow::Cow<'static, ::std::primitive::str> {
        std::borrow::Cow::Borrowed("EnumOption")
    }
    fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
        EnumOption::create_type_info(registry)
    }
    async fn resolve(
        &self,
        ctx: &::async_graphql::ContextSelectionSet<'_>,
        _field: &::async_graphql::Positioned<::async_graphql::parser::types::Field>,
    ) -> async_graphql::ServerResult<::async_graphql::Value> {
        async_graphql::resolver_utils::resolve_container(ctx, self).await
    }
}

#[cfg(feature = "graphql")]
impl async_graphql::ObjectType for EnumOptionRepresentation {}

impl EnumOptionRepresentation {
    #[must_use]
    pub const fn value(&self) -> &str {
        match self {
            Self::String(s) => s.as_str(),
            Self::Detailed(option) => option.value.as_str(),
        }
    }

    #[must_use]
    pub fn display_name(&self) -> MultiLanguageItem {
        match self {
            Self::String(s) => MultiLanguageItem::from_string(s.clone()),
            Self::Detailed(option) => option.display_name.clone(),
        }
    }

    #[must_use]
    pub fn as_detailed(&self) -> EnumOption {
        match self {
            Self::String(s) => EnumOption {
                value: s.clone(),
                display_name: MultiLanguageItem::from_string(s.clone()),
            },
            Self::Detailed(option) => option.clone(),
        }
    }
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "graphql", derive(async_graphql::SimpleObject))]
pub struct EnumSetting {
    pub name: MultiLanguageItem,
    pub description: MultiLanguageItem,
    pub values: Vec<EnumOptionRepresentation>,
    pub default: Option<String>,
    #[serde(default)]
    pub immutable: bool,
    #[serde(default = "true_default")]
    pub required: bool,
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "graphql", derive(async_graphql::SimpleObject))]
pub struct StringSetting {
    pub name: MultiLanguageItem,
    pub description: MultiLanguageItem,
    pub default: Option<String>,
    pub max_len: Option<usize>,
    pub string_type: Option<StringType>,
    #[serde(default = "true_default")]
    pub required: bool,
    pub placeholder: Option<MultiLanguageItem>,
    #[serde(default)]
    pub immutable: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "graphql", derive(async_graphql::SimpleObject))]
pub struct BoolSetting {
    pub name: MultiLanguageItem,
    pub description: MultiLanguageItem,
    pub default: bool,
    #[serde(default)]
    pub immutable: bool,
    #[serde(default = "true_default")]
    pub required: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "graphql", derive(async_graphql::SimpleObject))]
pub struct IntSetting {
    pub name: MultiLanguageItem,
    pub description: MultiLanguageItem,
    pub default: Option<i64>,
    pub min: Option<i64>,
    pub max: Option<i64>,
    pub step_size: Option<i64>,
    pub placeholder: Option<MultiLanguageItem>,
    #[serde(default)]
    pub immutable: bool,
    #[serde(default = "true_default")]
    pub required: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "graphql", derive(async_graphql::SimpleObject))]
pub struct FloatSetting {
    pub name: MultiLanguageItem,
    pub description: MultiLanguageItem,
    pub default: Option<f64>,
    pub min: Option<f64>,
    pub max: Option<f64>,
    pub step_size: Option<f64>,
    pub placeholder: Option<MultiLanguageItem>,
    #[serde(default)]
    pub immutable: bool,
    #[serde(default = "true_default")]
    pub required: bool,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(tag = "type")]
#[cfg_attr(feature = "graphql", derive(async_graphql::Interface))]
#[cfg_attr(
    feature = "graphql",
    graphql(
        name = "SettingDetails",
        field(name = "name", ty = "&MultiLanguageItem"),
        field(name = "description", ty = "&MultiLanguageItem"),
        field(name = "immutable", ty = "&bool"),
        field(name = "required", ty = "&bool"),
    )
)]
pub enum Setting {
    Enum(EnumSetting),
    String(StringSetting),
    Bool(BoolSetting),
    Int(IntSetting),
    Float(FloatSetting),
}

#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "graphql", derive(async_graphql::Enum))]
pub enum StringType {
    #[serde(rename = "password")]
    Password,
    #[serde(rename = "email")]
    Email,
    #[serde(rename = "url")]
    Url,
    #[serde(rename = "ip")]
    Ip,
}

impl Setting {
    #[must_use]
    pub fn default_value(&self) -> serde_json::Value {
        match self {
            Self::Enum(details) => match details.default.as_ref() {
                Some(default) => serde_json::Value::String(default.clone()),
                None => serde_json::Value::Null,
            },
            Self::String(details) => match details.default.as_ref() {
                Some(default) => serde_json::Value::String(default.clone()),
                None => serde_json::Value::Null,
            },
            Self::Bool(details) => serde_json::Value::Bool(details.default),
            Self::Int(details) => match details.default.as_ref() {
                Some(default) => serde_json::Value::Number(serde_json::Number::from(*default)),
                None => serde_json::Value::Null,
            },
            Self::Float(details) => match details.default.as_ref() {
                Some(default) => {
                    serde_json::Value::Number(serde_json::Number::from_f64(*default).unwrap())
                }
                None => serde_json::Value::Null,
            },
        }
    }
}