diff --git a/Cargo.lock b/Cargo.lock index 6bf4ad71..d30e6466 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,6 +83,7 @@ dependencies = [ "aardwolf-models", "aardwolf-types", "aardwolf-yew-frontend", + "ahash", "config", "gettext", "gettext-macros", @@ -563,12 +564,6 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "async-trait" version = "0.1.83" @@ -613,12 +608,6 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.20.0" @@ -674,18 +663,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitvec" -version = "0.19.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -910,7 +887,7 @@ dependencies = [ "convert_case 0.6.0", "json5", "lazy_static", - "nom 7.1.3", + "nom", "pathdiff", "ron", "rust-ini", @@ -1435,12 +1412,6 @@ dependencies = [ "percent-encoding 2.3.1", ] -[[package]] -name = "funty" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" - [[package]] name = "futures" version = "0.1.31" @@ -2213,16 +2184,16 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" name = "itertools" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -2274,19 +2245,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec", - "bitflags 1.3.2", - "cfg-if", - "ryu", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.159" @@ -2433,19 +2391,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "nom" -version = "6.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" -dependencies = [ - "bitvec", - "funty", - "lexical-core", - "memchr", - "version_check", -] - [[package]] name = "nom" version = "7.1.3" @@ -2882,12 +2827,6 @@ dependencies = [ "scheduled-thread-pool", ] -[[package]] -name = "radium" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" - [[package]] name = "rand" version = "0.8.5" @@ -2997,15 +2936,15 @@ checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] name = "ructe" -version = "0.13.4" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fd2f3b927021cc8586d365c36d16d82d91fdae0a3839819c12c8e86e0f929e" +checksum = "21f419ac323a5c6a32126d24f1d859a348a963105373d0f45fb851f0b8dff52d" dependencies = [ - "base64 0.13.1", + "base64 0.22.1", "bytecount", - "itertools 0.10.5", + "itertools 0.13.0", "md5", - "nom 6.1.2", + "nom", ] [[package]] @@ -3325,12 +3264,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.11.1" @@ -3411,12 +3344,6 @@ dependencies = [ "utf8-cstr", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "tempfile" version = "3.12.0" @@ -4056,12 +3983,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "wyz" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" - [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/aardwolf-templates/Cargo.toml b/aardwolf-templates/Cargo.toml index a698722c..5744d583 100644 --- a/aardwolf-templates/Cargo.toml +++ b/aardwolf-templates/Cargo.toml @@ -7,12 +7,13 @@ build = "build.rs" [build-dependencies] config = "0.14.0" -ructe = "^0.13.4" # Careted to require exactly 0.13 because newer versions break the build. +ructe = "0.17.2" # Careted to require exactly 0.13 because newer versions break the build. [dependencies] gettext = "0.4" gettext-macros = "0.6.1" gettext-utils = "0.1.0" +rust-i18n = "3" # Adding rust-i18n for handling localization [dependencies.rocket_i18n] version = "0.4.1" @@ -32,11 +33,6 @@ path = "../aardwolf-models" version = "0.1.0" path = "../aardwolf-yew-frontend" -#- -# Adding rust-i18n for handling localization -[dependencies] -rust-i18n = "3" - #- # Adding syn for template compilation [dependencies.syn] diff --git a/aardwolf-templates/src/asides/shortcuts.rs b/aardwolf-templates/src/asides/shortcuts.rs index 2b056ef8..5e359532 100644 --- a/aardwolf-templates/src/asides/shortcuts.rs +++ b/aardwolf-templates/src/asides/shortcuts.rs @@ -5,3 +5,13 @@ pub struct Shortcuts<'a> { pub(crate) profile_link: &'a str, pub(crate) username: &'a str, } + +impl<'a> Shortcuts<'a> { + pub fn new(catalog: &'a Catalog, profile_link: &'a str, username: &'a str) -> Self { + Self { + catalog, + profile_link, + username, + } + } +} diff --git a/aardwolf-templates/src/elements/alert.rs b/aardwolf-templates/src/elements/alert.rs index 42d61881..6ecf28cc 100644 --- a/aardwolf-templates/src/elements/alert.rs +++ b/aardwolf-templates/src/elements/alert.rs @@ -18,7 +18,7 @@ impl std::fmt::Display for AlertKind { write!(f, "{}", s) } } - +#[derive(Debug)] pub struct Alert { pub(crate) kind: AlertKind, pub(crate) message: String, diff --git a/aardwolf-templates/src/elements/input.rs b/aardwolf-templates/src/elements/input.rs index d28159ff..dd173b54 100644 --- a/aardwolf-templates/src/elements/input.rs +++ b/aardwolf-templates/src/elements/input.rs @@ -50,20 +50,6 @@ impl<'a> From<&'a InputEmail<'a>> for Input<'a> { } } -impl<'a> From<&'a InputText<'a>> for Input<'a> { - fn from(t: &'a InputText<'a>) -> Self { - Input { - kind: "text", - name: t.name, - label: Some(t.label.clone()), - placeholder: t.placeholder.clone(), - icon: t.icon, - value: t.value, - error: t.error.clone(), - } - } -} - pub struct InputPassword<'a> { pub(crate) name: &'a str, pub(crate) label: String, @@ -86,15 +72,6 @@ pub struct InputEmail<'a> { pub(crate) error: Option, } -pub struct InputText<'a> { - pub(crate) name: &'a str, - pub(crate) label: String, - pub(crate) placeholder: Option, - pub(crate) icon: Option<&'a str>, - pub(crate) value: &'a str, - pub(crate) error: Option, -} - pub struct InputCheckbox<'a> { pub(crate) name: &'a str, pub(crate) label: String, @@ -102,3 +79,10 @@ pub struct InputCheckbox<'a> { pub(crate) checked: bool, pub(crate) error: Option, } + +pub enum InputKind { + Text, + Checkbox, + Select, + +} \ No newline at end of file diff --git a/aardwolf-templates/src/elements/input_select.rs b/aardwolf-templates/src/elements/input_select.rs index 1708d5cf..d4d0ceb6 100644 --- a/aardwolf-templates/src/elements/input_select.rs +++ b/aardwolf-templates/src/elements/input_select.rs @@ -2,55 +2,109 @@ use aardwolf_models::sql_types::{FollowPolicy, PostVisibility}; use gettext::Catalog; use gettext_macros::i18n; +#[derive(Clone, Debug, PartialEq)] pub struct InputSelect<'a> { - pub(crate) name: &'a str, - pub(crate) label: String, + pub name: &'a str, + pub label: String, + pub selected_value: String, + pub options: Vec>, + pub error: Option, pub(crate) selected: String, - pub(crate) options: Vec>, - pub(crate) error: Option, +} + +impl<'a> Default for InputSelect<'a> { + fn default() -> Self { + InputSelect { + name: "", + label: "".to_string(), + selected_value: "".to_string(), + options: vec![], + error: None, + selected: "".to_string(), // Add this line to provide a value for the selected field + } + } } impl<'a> InputSelect<'a> { - pub(crate) fn follow_policy_options(catalog: &Catalog) -> Vec { - vec![ - SelectOption { - value: FollowPolicy::AutoAccept.into(), - display: i18n!(catalog, "Automatically accept new followers"), - }, - SelectOption { - value: FollowPolicy::AutoReject.into(), - display: i18n!(catalog, "Automatically reject new followers"), - }, - SelectOption { - value: FollowPolicy::ManualReview.into(), - display: i18n!(catalog, "Manually review new followers"), - }, - ] + pub fn new( + name: &'a str, + label: Option<&str>, + value: &str, + error: Option<&str>, + ) -> Self { + Self { + name, + label: label.map(|l| l.to_string()).unwrap_or_default(), + selected_value: value.to_string(), + options: Vec::new(), + error: error.map(|e| e.to_string()), + selected: value.to_string(), + } } - pub(crate) fn visibility_options(catalog: &Catalog) -> Vec { - vec![ - SelectOption { - value: PostVisibility::Public.into(), - display: i18n!(catalog, "Visible to everyone"), - }, - SelectOption { - value: PostVisibility::FollowersOnly.into(), - display: i18n!(catalog, "Visible to followers"), - }, - SelectOption { - value: PostVisibility::FriendsOnly.into(), - display: i18n!(catalog, "Visible to mutuals"), - }, - SelectOption { - value: PostVisibility::ListedPeopleOnly.into(), - display: i18n!(catalog, "Only visible to mentioned users"), - }, - ] + pub fn with_visibility_options(catalog: &'a Catalog) -> Self { + Self { + name: "visibility", + label: i18n!(catalog, "Post visibility"), + selected_value: PostVisibility::Public.to_string(), + options: visibility_options(catalog), + error: None, + selected: PostVisibility::Public.to_string(), + } } } +#[derive(Clone, Debug, PartialEq)] pub struct SelectOption<'a> { - pub(crate) value: &'a str, - pub(crate) display: String, + pub value: &'a str, + pub display: String, +} + +fn follow_policy_options(catalog: &Catalog) -> Vec> { + vec![ + SelectOption { + value: FollowPolicy::AutoAccept.into(), + display: i18n!(catalog, "Automatically accept new followers"), + }, + SelectOption { + value: FollowPolicy::AutoReject.into(), + display: i18n!(catalog, "Automatically reject new followers"), + }, + SelectOption { + value: FollowPolicy::ManualReview.into(), + display: i18n!(catalog, "Manually review new followers"), + }, + ] +} + +fn visibility_options(catalog: &Catalog) -> Vec> { + vec![ + SelectOption { + value: PostVisibility::Public.into(), + display: i18n!(catalog, "Visible to everyone"), + }, + SelectOption { + value: PostVisibility::FollowersOnly.into(), + display: i18n!(catalog, "Visible to followers"), + }, + SelectOption { + value: PostVisibility::FriendsOnly.into(), + display: i18n!(catalog, "Visible to mutuals"), + }, + SelectOption { + value: PostVisibility::ListedPeopleOnly.into(), + display: i18n!(catalog, "Only visible to mentioned users"), + }, + ] +} + +impl InputSelect<'_> { + pub fn with_follow_policy_options(catalog: &Catalog) -> Vec> { + follow_policy_options(catalog) + } +} + +enum ValidateFollowPolicyFail { + Listed, + // Other variants... } diff --git a/aardwolf-templates/src/elements/input_text.rs b/aardwolf-templates/src/elements/input_text.rs new file mode 100644 index 00000000..da21e6d1 --- /dev/null +++ b/aardwolf-templates/src/elements/input_text.rs @@ -0,0 +1,56 @@ +use super::input::Input; + +#[derive(Debug)] +pub struct InputText<'a> { + pub name: &'a str, + pub label: String, + pub placeholder: Option, + pub icon: Option<&'a str>, + pub value: &'a str, + pub error: Option, +} + +impl<'a> Default for InputText<'a> { + fn default() -> Self { + Self { + name: "", + label: String::new(), + placeholder: None, + icon: None, + value: "", + error: None, + } + } +} + +impl<'a> InputText<'a> { + pub fn new( + name: &'a str, + label: Option<&'a str>, + value: Option<&'a str>, + error: Option<&'a str>, + ) -> Self { + Self { + name, + label: label.map_or_else(String::new, Into::into), + value: value.unwrap_or(""), + error: error.map(Into::into), + ..Default::default() + } + } +} + +impl<'a> From<&'a InputText<'a>> for Input<'a> { + fn from(input_text: &'a InputText<'a>) -> Self { + Self { + kind: "text", + name: input_text.name, + label: Some(input_text.label.clone()), + placeholder: input_text.placeholder.clone(), + icon: input_text.icon, + value: input_text.value, + error: input_text.error.clone(), + } + } +} + diff --git a/aardwolf-templates/src/elements/input_textarea.rs b/aardwolf-templates/src/elements/input_textarea.rs index a13211ab..42249938 100644 --- a/aardwolf-templates/src/elements/input_textarea.rs +++ b/aardwolf-templates/src/elements/input_textarea.rs @@ -1,8 +1,39 @@ +#[derive(Debug)] pub struct InputTextarea<'a> { - pub(crate) name: &'a str, - pub(crate) label: Option, - pub(crate) icon: Option<&'a str>, - pub(crate) placeholder: Option, - pub(crate) value: &'a str, - pub(crate) error: Option, + pub name: &'a str, + pub label: Option, + pub icon: Option<&'a str>, + pub placeholder: Option, + pub value: &'a str, + pub error: Option, +} + +impl<'a> Default for InputTextarea<'a> { + fn default() -> Self { + Self { + name: "", + label: None, + icon: None, + placeholder: None, + value: "", + error: None, + } + } +} + +impl<'a> InputTextarea<'a> { + pub fn new( + name: &'a str, + label: Option<&'a str>, + value: Option<&'a str>, + error: Option<&'a str>, + ) -> Self { + Self { + name, + label: label.map(ToString::to_string), + value: value.unwrap_or_default(), + error: error.map(ToString::to_string), + ..Default::default() + } + } } diff --git a/aardwolf-templates/src/elements/mod.rs b/aardwolf-templates/src/elements/mod.rs index 178ba6de..1bfcebfc 100644 --- a/aardwolf-templates/src/elements/mod.rs +++ b/aardwolf-templates/src/elements/mod.rs @@ -1,19 +1,13 @@ -mod alert; -mod input; -mod input_select; -mod input_textarea; -mod lang_dropdown; -mod notification_content; -mod notification_dropdown; -mod search_bar; +pub mod alert; +pub mod input; +pub mod input_select; +pub mod input_text; +pub mod input_textarea; +pub mod lang_dropdown; +pub mod notification_content; +pub mod notification_dropdown; +pub mod search_bar; + +pub use notification_dropdown::NotificationDropdown; +pub use lang_dropdown::LangDropdown; -pub use self::{ - alert::{Alert, AlertKind}, - input::{Input, InputCheckbox, InputEmail, InputPassword, InputPasswordConfirm, InputText}, - input_select::{InputSelect, SelectOption}, - input_textarea::InputTextarea, - lang_dropdown::*, - notification_content::*, - notification_dropdown::*, - search_bar::*, -}; diff --git a/aardwolf-templates/src/elements/notification_content.rs b/aardwolf-templates/src/elements/notification_content.rs index e9e5dd04..9baafdbb 100644 --- a/aardwolf-templates/src/elements/notification_content.rs +++ b/aardwolf-templates/src/elements/notification_content.rs @@ -1,5 +1,8 @@ use gettext::Catalog; +/// A struct representing the content of a notification. pub struct NotificationContent<'a> { - pub(crate) catalog: &'a Catalog, + /// The translation catalog to use for translating the notification content. + pub catalog: &'a Catalog, } + diff --git a/aardwolf-templates/src/elements/notification_dropdown.rs b/aardwolf-templates/src/elements/notification_dropdown.rs index bb082a36..9e494865 100644 --- a/aardwolf-templates/src/elements/notification_dropdown.rs +++ b/aardwolf-templates/src/elements/notification_dropdown.rs @@ -1,5 +1,9 @@ use gettext::Catalog; +/// A dropdown menu for displaying notifications. +#[derive(Debug)] pub struct NotificationDropdown<'a> { - pub(crate) catalog: &'a Catalog, + /// The gettext catalog for translating strings. + catalog: &'a Catalog, } + diff --git a/aardwolf-templates/src/first_login.rs b/aardwolf-templates/src/first_login.rs index 4381fca8..9f9ba302 100644 --- a/aardwolf-templates/src/first_login.rs +++ b/aardwolf-templates/src/first_login.rs @@ -1,103 +1,131 @@ + use aardwolf_types::forms::personas::{ - PersonaCreationFormState, ValidateDisplayNameFail, ValidatePersonaCreationFail, - ValidateShortnameFail, + PersonaCreationFormState, ValidateDisplayNameFail, ValidateFollowPolicyFail, ValidateIsSearchableFail, ValidatePersonaCreationFail, ValidateShortnameFail }; use gettext::Catalog; use gettext_macros::i18n; -use crate::{Alert, AlertKind, InputCheckbox, InputSelect, InputText, Renderable}; +use crate::elements::{alert::{Alert, AlertKind}, input, input_select}; pub struct FirstLogin<'a> { - pub(crate) catalog: &'a Catalog, - pub(crate) csrf: &'a str, - pub(crate) alert: Option, - pub(crate) display_name: InputText<'a>, - pub(crate) shortname: InputText<'a>, - pub(crate) follow_policy: InputSelect<'a>, - pub(crate) default_visibility: InputSelect<'a>, - pub(crate) is_searchable: InputCheckbox<'a>, + pub catalog: &'a Catalog, + pub csrf_token: &'a str, + pub alert: Option, + pub display_name_input: input::Input<'a>, + pub shortname_input: input::Input<'a>, + pub follow_policy_input: input_select::InputSelect<'a>, + pub default_visibility_input: input_select::InputSelect<'a>, + pub is_searchable_input: input::InputCheckbox<'a>, } impl<'a> FirstLogin<'a> { - #[allow(clippy::too_many_arguments)] pub fn new( catalog: &'a Catalog, - csrf: &'a str, + csrf_token: &'a str, state: &'a PersonaCreationFormState, validation_error: Option<&'a ValidatePersonaCreationFail>, - server_error: bool, ) -> Self { + let alert = match validation_error { + Some(_error) => Some(Alert { + kind: AlertKind::Error, + message: i18n!(catalog, "There was an error creating your persona"), + }), + None => None, + }; + FirstLogin { catalog, - csrf, - alert: if server_error { - Some(Alert { - kind: AlertKind::Error, - message: i18n!(catalog, "There was an error creating your persona"), - }) - } else { - None - }, - display_name: InputText { + csrf_token, + alert, + display_name_input: input::Input { name: "display_name", - label: i18n!(catalog, "Display Name"), - icon: None, + label: Some(i18n!(catalog, "Display Name")), placeholder: Some(i18n!(catalog, "Display name")), value: &state.display_name, - error: validation_error.and_then(|e| { - e.display_name.as_ref().map(|e| match *e { + error: validation_error + .and_then(|e| e.display_name.as_ref()) + .map(|e| match e { ValidateDisplayNameFail::Empty => { i18n!(catalog, "Display name must not be empty") } - }) - }), + }), + icon: Some("fas fa-user"), + kind: "text", }, - shortname: InputText { + shortname_input: input::Input { name: "shortname", - label: i18n!(catalog, "Username"), - icon: None, + label: Some(i18n!(catalog, "Username")), placeholder: Some(i18n!(catalog, "Username")), value: &state.shortname, - error: validation_error.and_then(|e| { - e.shortname.as_ref().map(|e| match *e { + error: validation_error + .and_then(|e| e.shortname.as_ref()) + .map(|e| match e { ValidateShortnameFail::Empty => { i18n!(catalog, "Username must not be empty") } ValidateShortnameFail::SpecialCharacters => { i18n!(catalog, "Username must not contain special characters") } - ValidateShortnameFail::TooLong => i18n!(catalog, "Username is too long"), - }) - }), - }, - follow_policy: InputSelect { - name: "follow_policy", - label: i18n!(catalog, "Follow Policy"), - selected: state.follow_policy.to_string(), - options: InputSelect::follow_policy_options(catalog), - error: validation_error.and_then(|e| e.follow_policy.as_ref().map(|e| match *e {})), + ValidateShortnameFail::TooLong => { + i18n!(catalog, "Username is too long") + } + }), + icon: Some("fas fa-user"), + kind: "text", }, - default_visibility: InputSelect { + default_visibility_input: input_select::InputSelect { name: "default_visibility", label: i18n!(catalog, "Post Visibility"), selected: state.default_visibility.to_string(), - options: InputSelect::visibility_options(catalog), + options: input_select::InputSelect::with_visibility_options(catalog).options, error: validation_error - .and_then(|e| e.default_visibility.as_ref().map(|e| match *e {})), + .and_then(|e| e.is_searchable.as_ref()) + .map(|e| match e { + ValidateIsSearchableFail::SomeError => { + i18n!(catalog, "Some error message") + } + ValidateIsSearchableFail::Invalid => todo!(), + // Add arms for other possible values of ValidateIsSearchableFail + }), + selected_value: state.default_visibility.to_string(), }, - is_searchable: InputCheckbox { + is_searchable_input: input::InputCheckbox { name: "is_searchable", label: i18n!(catalog, "Allow people to search for this profile"), - icon: None, checked: state.is_searchable, - error: validation_error.and_then(|e| e.is_searchable.as_ref().map(|e| match *e {})), + error: validation_error + .and_then(|e| e.is_searchable.as_ref()) + .map(|e| match e { + ValidateIsSearchableFail::Invalid => { + i18n!(catalog, "Invalid value for `is_searchable`") + } + ValidateIsSearchableFail::SomeError => { + i18n!(catalog, "Some error message") + }, + }), + icon: Some("fas fa-user"), + }, + follow_policy_input: input_select::InputSelect { + name: "follow_policy", + label: i18n!(catalog, "Follow Policy"), + selected: state.follow_policy.to_string(), + options: input_select::InputSelect::with_follow_policy_options(catalog), + error: validation_error + .and_then(|e| e.follow_policy.as_ref()) + .map(|e| match e { + ValidateFollowPolicyFail::Invalid => { + i18n!(catalog, "Invalid follow policy") + } + }), + selected_value: state.follow_policy.to_string(), }, } } } -impl<'a> Renderable for FirstLogin<'a> { - fn render(&self, write: &mut dyn std::io::Write) -> std::io::Result<()> { - crate::templates::first_login(write, self) +impl<'a> crate::Renderable for FirstLogin<'a> { + fn render(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()> { + crate::templates::first_login_html(writer, self) } } + diff --git a/aardwolf-templates/src/home/feed.rs b/aardwolf-templates/src/home/feed.rs index 6e2cb870..7c472e14 100644 --- a/aardwolf-templates/src/home/feed.rs +++ b/aardwolf-templates/src/home/feed.rs @@ -1,4 +1,5 @@ use gettext::Catalog; +use std::io::{Write, Result}; use crate::Renderable; @@ -12,9 +13,10 @@ impl<'a> Feed<'a> { } } - impl<'a> Renderable for Feed<'a> { - fn render(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()> { - crate::templates::home::feed(writer, self) + fn render(&self, writer: &mut dyn Write) -> Result<()> { + write!(writer, "{}", self.catalog.gettext("This is the feed template"))?; + writer.flush()?; // Ensure the writer is flushed after writing + Ok(()) } -} +} \ No newline at end of file diff --git a/aardwolf-templates/src/home/home.rs b/aardwolf-templates/src/home/home.rs index 66c137ae..e3d1c9fe 100644 --- a/aardwolf-templates/src/home/home.rs +++ b/aardwolf-templates/src/home/home.rs @@ -1,24 +1,19 @@ -use aardwolf_types::forms::posts::{ - PostCreationFormState, ValidatePostCreationFail, ValidateSourceError, -}; +use aardwolf_types::forms::posts::{PostCreationFormState, ValidatePostCreationFail}; use gettext::Catalog; -use gettext_macros::i18n; use crate::{ asides::Shortcuts, - elements::{Alert, AlertKind, InputSelect, InputText, InputTextarea}, - home::Feed, - home::NavTop, + home::{feed::Feed, nav_top::NavTop}, posts::NewPost, Renderable, }; pub struct Home<'a> { - pub(crate) catalog: &'a Catalog, - pub(crate) new_post: NewPost<'a>, - pub(crate) shortcuts: Shortcuts<'a>, - pub(crate) nav_top: NavTop<'a>, - pub(crate) feed: Feed<'a>, + pub catalog: &'a Catalog, + pub shortcuts: Shortcuts<'a>, + pub nav_top: NavTop<'a>, + pub feed: Feed<'a>, + pub new_post: NewPost<'a>, } impl<'a> Home<'a> { @@ -26,67 +21,23 @@ impl<'a> Home<'a> { catalog: &'a Catalog, profile_link: &'a str, username: &'a str, - csrf: &'a str, - state: &'a PostCreationFormState, + csrf_token: &'a str, + form_state: &'a PostCreationFormState, validation_error: Option<&'a ValidatePostCreationFail>, - server_error: bool, ) -> Self { - Home { + Self { catalog, - nav_top: NavTop { catalog }, - new_post: NewPost { - csrf, - alert: if server_error { - Some(Alert { - kind: AlertKind::Error, - message: i18n!(catalog, "There was an error creating your post"), - }) - } else { - None - }, - catalog: &catalog, - username: username, - source: InputTextarea { - name: "source", - label: None, - icon: None, - placeholder: Some(i18n!(catalog, "What's on your mind?")), - value: &state.source, - error: validation_error.and_then(|e| { - e.source.as_ref().map(|e| match *e { - ValidateSourceError::Empty => i18n!(catalog, "Post cannot be empty"), - }) - }), - }, - visibility: InputSelect { - name: "visibility", - label: i18n!(catalog, "Post Visibility"), - selected: state.visibility.to_string(), - options: InputSelect::visibility_options(catalog), - error: validation_error - .and_then(|e| e.visibility.as_ref().map(|e| match *e {})), - }, - name: InputText { - name: "name", - label: i18n!(catalog, "Content Warning"), - icon: None, - placeholder: Some(i18n!(catalog, "mh, nsfw, etc.")), - value: state.name.as_ref().map(|s| (*s).as_ref()).unwrap_or(""), - error: validation_error.and_then(|e| e.name.as_ref().map(|e| match *e {})), - }, - }, - feed: Feed { catalog }, - shortcuts: Shortcuts { - catalog, - profile_link, - username, - }, + shortcuts: Shortcuts::new(catalog, profile_link, username), + nav_top: NavTop::new(catalog), + feed: Feed::new(catalog), + new_post: NewPost::new(catalog, csrf_token, form_state, validation_error), } } } impl<'a> Renderable for Home<'a> { fn render(&self, write: &mut dyn std::io::Write) -> std::io::Result<()> { - crate::templates::home::home(write, self) + crate::templates::home::home_html(write, self) } } + diff --git a/aardwolf-templates/src/home/mod.rs b/aardwolf-templates/src/home/mod.rs index 84040e67..c19ea100 100644 --- a/aardwolf-templates/src/home/mod.rs +++ b/aardwolf-templates/src/home/mod.rs @@ -1,7 +1,3 @@ -mod feed; -mod home; -mod nav_top; - -pub use feed::Feed; -pub use home::Home; -pub use nav_top::NavTop; +pub mod feed; +pub mod home; +pub mod nav_top; diff --git a/aardwolf-templates/src/home/nav_top.rs b/aardwolf-templates/src/home/nav_top.rs index 9fccb2c6..6e39b266 100644 --- a/aardwolf-templates/src/home/nav_top.rs +++ b/aardwolf-templates/src/home/nav_top.rs @@ -1,19 +1,11 @@ use gettext::Catalog; -use crate::Renderable; - pub struct NavTop<'a> { pub(crate) catalog: &'a Catalog, } impl<'a> NavTop<'a> { pub fn new(catalog: &'a Catalog) -> Self { - NavTop { catalog } - } -} - -impl<'a> Renderable for NavTop<'a> { - fn render(&self, write: &mut dyn std::io::Write) -> std::io::Result<()> { - crate::templates::home::nav_top(write, self) + Self { catalog } } } diff --git a/aardwolf-templates/src/lib.rs b/aardwolf-templates/src/lib.rs index 64c2ffbe..c2d66d9e 100644 --- a/aardwolf-templates/src/lib.rs +++ b/aardwolf-templates/src/lib.rs @@ -1,14 +1,10 @@ -#![allow(clippy::inline_fn_without_body)] -#![allow(clippy::into_iter_on_ref)] - -use gettext_macros::{compile_i18n, include_i18n, init_i18n}; +use gettext_macros::init_i18n; use rocket_i18n::Translations; init_i18n!("aardwolf", en, pl); include!(concat!(env!("OUT_DIR"), "/templates.rs")); -// Directories pub mod asides; pub mod containers; pub mod elements; @@ -16,27 +12,16 @@ pub mod error; pub mod home; pub mod posts; -// Root-level files -mod first_login; -mod sign_in; -mod sign_up; - -pub use self::{first_login::*, sign_in::*, sign_up::*}; - -use self::{ - asides::Shortcuts, - elements::{ - Alert, AlertKind, Input, InputCheckbox, InputEmail, InputPassword, InputSelect, InputText, - InputTextarea, - }, -}; +pub mod first_login; +pub mod sign_in; +pub mod sign_up; pub trait Renderable { - fn render(&self, _: &mut dyn std::io::Write) -> std::io::Result<()>; + fn render(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()>; } /// Returns an empty Translations object to disable translations due to issues with the gettext library. -pub fn managed_state() -> Translations { - // gettext is not behaving correctly, so translations are disabled until a replacement is found - Vec::new() +pub fn disabled_translations() -> Translations { + Translations::default() } + diff --git a/aardwolf-templates/src/posts/mod.rs b/aardwolf-templates/src/posts/mod.rs index f877eaee..236f9d97 100644 --- a/aardwolf-templates/src/posts/mod.rs +++ b/aardwolf-templates/src/posts/mod.rs @@ -1,4 +1,5 @@ -mod new_post; -mod reply_post; +pub mod new_post; +pub mod reply_post; pub use self::{new_post::NewPost, reply_post::ReplyPost}; + diff --git a/aardwolf-templates/src/posts/new_post.rs b/aardwolf-templates/src/posts/new_post.rs index 96aad28e..0249bb0e 100644 --- a/aardwolf-templates/src/posts/new_post.rs +++ b/aardwolf-templates/src/posts/new_post.rs @@ -1,13 +1,68 @@ +use aardwolf_types::forms::posts::{PostCreationFormState, ValidatePostCreationForm}; use gettext::Catalog; -use crate::elements::{Alert, InputSelect, InputText, InputTextarea}; +use crate::elements::{ + alert::{Alert, AlertKind}, + input_select::InputSelect, + input_text::InputText, + input_textarea::InputTextarea, +}; pub struct NewPost<'a> { - pub(crate) csrf: &'a str, - pub(crate) alert: Option, - pub(crate) catalog: &'a Catalog, - pub(crate) username: &'a str, - pub(crate) source: InputTextarea<'a>, - pub(crate) visibility: InputSelect<'a>, - pub(crate) name: InputText<'a>, + csrf_token: &'a str, + alert: Option, + catalog: &'a Catalog, + username: Option<&'a str>, + source: InputTextarea<'a>, + visibility: InputSelect<'a>, + name: InputText<'a>, +} + +impl<'a> NewPost<'a> { + pub fn new( + catalog: &'a Catalog, + csrf_token: &'a str, + form_state: &'a PostCreationFormState, + validation_error: Option<&'a ValidatePostCreationForm>, + ) -> Self { + let username = form_state.username; + let alert = validation_error.map(|e| Alert { + kind: AlertKind::Error, + message: e.to_string(), + }); + + NewPost { + csrf_token, + alert, + catalog, + username: Some(username.as_ref()), + source: InputTextarea::new( + "source", + Some(catalog.gettext("Post source")), + Some(form_state.source.as_str()), + validation_error + .and_then(|e| e.source.as_deref()) + .map(ToString::to_string) + .as_deref(), + ), + visibility: InputSelect::new( + "visibility", + Some(catalog.gettext("Post visibility")), + form_state.visibility.into(), + validation_error + .and_then(|e| e.source) + .map(|e| e.to_string()) + .as_deref(), + ), + name: InputText::new( + "name", + Some(catalog.gettext("Post name")), + form_state.name.as_deref(), + validation_error + .and_then(|e| e.name) + .map(|e| e.to_string()) + .as_deref(), + ), + } + } } diff --git a/aardwolf-templates/src/posts/reply_post.rs b/aardwolf-templates/src/posts/reply_post.rs index 9e0b3694..2b089f7f 100644 --- a/aardwolf-templates/src/posts/reply_post.rs +++ b/aardwolf-templates/src/posts/reply_post.rs @@ -1,13 +1,14 @@ use gettext::Catalog; -use crate::elements::{Alert, InputSelect, InputText, InputTextarea}; +use crate::elements::{alert::Alert, input_select::InputSelect, input_text::InputText, input_textarea::InputTextarea}; +#[derive(Debug)] pub struct ReplyPost<'a> { - pub(crate) catalog: &'a Catalog, - pub(crate) csrf: &'a str, - pub(crate) alert: Option, - pub(crate) username: &'a str, - pub(crate) source: InputTextarea<'a>, - pub(crate) visibility: InputSelect<'a>, - pub(crate) name: InputText<'a>, + pub catalog: &'a Catalog, + pub csrf_token: &'a str, + pub alert: Option, + pub author: &'a str, + pub source: InputTextarea<'a>, + pub visibility: InputSelect<'a>, + pub title: InputText<'a>, } diff --git a/aardwolf-templates/src/sign_in.rs b/aardwolf-templates/src/sign_in.rs index ed55291f..1f5238d9 100644 --- a/aardwolf-templates/src/sign_in.rs +++ b/aardwolf-templates/src/sign_in.rs @@ -5,7 +5,9 @@ use aardwolf_types::forms::auth::{ use gettext::Catalog; use gettext_macros::i18n; -use crate::{Alert, AlertKind, InputEmail, InputPassword, Renderable}; +use crate:: Renderable; +use crate::elements::alert::{Alert, AlertKind}; +use crate::elements::input::{InputEmail, InputPassword}; pub struct SignIn<'a> { pub(crate) catalog: &'a Catalog, @@ -63,6 +65,6 @@ impl<'a> SignIn<'a> { impl<'a> Renderable for SignIn<'a> { fn render(&self, write: &mut dyn std::io::Write) -> std::io::Result<()> { - crate::templates::sign_in(write, self) + crate::templates::sign_in_html(write, self) } } diff --git a/aardwolf-templates/src/sign_up.rs b/aardwolf-templates/src/sign_up.rs index fdbee86b..2afcb36e 100644 --- a/aardwolf-templates/src/sign_up.rs +++ b/aardwolf-templates/src/sign_up.rs @@ -5,8 +5,9 @@ use aardwolf_types::forms::auth::{ use gettext::Catalog; use gettext_macros::i18n; -use crate::{Alert, AlertKind, InputEmail, InputPassword, Renderable}; - +use crate::Renderable; +use crate::elements::alert::{Alert, AlertKind}; +use crate::elements::input::{InputEmail, InputPassword}; pub struct SignUp<'a> { pub(crate) catalog: &'a Catalog, @@ -86,6 +87,6 @@ impl<'a> SignUp<'a> { impl<'a> Renderable for SignUp<'a> { fn render(&self, write: &mut dyn std::io::Write) -> std::io::Result<()> { - crate::templates::sign_up(write, self) + crate::templates::sign_up_html(write, self) } } diff --git a/aardwolf-templates/templates/asides/settings.rs.html b/aardwolf-templates/templates/asides/settings.rs.html index 887754af..41e6a757 100644 --- a/aardwolf-templates/templates/asides/settings.rs.html +++ b/aardwolf-templates/templates/asides/settings.rs.html @@ -5,27 +5,28 @@ + diff --git a/aardwolf-templates/templates/asides/shortcuts.rs.html b/aardwolf-templates/templates/asides/shortcuts.rs.html index 43c3c5e2..5a89eabb 100644 --- a/aardwolf-templates/templates/asides/shortcuts.rs.html +++ b/aardwolf-templates/templates/asides/shortcuts.rs.html @@ -1,17 +1,15 @@ -@use gettext_macros::i18n; - -@use crate::{Shortcuts, templates::elements::icon}; +@use crate::templates::elements::icon; @(shortcuts: &Shortcuts) + diff --git a/aardwolf-templates/templates/base.rs.html b/aardwolf-templates/templates/base.rs.html index 0abf13dc..a0e3264a 100644 --- a/aardwolf-templates/templates/base.rs.html +++ b/aardwolf-templates/templates/base.rs.html @@ -1,13 +1,13 @@ -@use gettext::Catalog; -@use crate::templates::{footer, html_head}; +@use super::{footer, html_head}; -@(catalog: &Catalog, title: &str, content: Content) +@(catalog: &Catalog, title: &str, page_content: Content) - @:html_head(title) + @:html_head(&catalog, title) - @:content() + @:page_content() + @:footer(&catalog) - @:footer(catalog) + diff --git a/aardwolf-templates/templates/elements/alert.rs.html b/aardwolf-templates/templates/elements/alert.rs.html index 497399ee..269b5903 100644 --- a/aardwolf-templates/templates/elements/alert.rs.html +++ b/aardwolf-templates/templates/elements/alert.rs.html @@ -1,12 +1,25 @@ -@use crate::{Alert, templates::elements::icon}; +@use crate::{Alert, AlertKind, templates::elements::icon}; @(alert: &Alert) -
+
"warning", + AlertKind::Error => "error", + AlertKind::Success => "success", +}"> +
- @:icon("warning") + @:icon(match alert.kind { + AlertKind::Info => "info-circle", + AlertKind::Warning => "exclamation-triangle", + AlertKind::Error => "exclamation-circle", + AlertKind::Success => "check-circle", + })
+
@alert.message
+ diff --git a/aardwolf-templates/templates/elements/icon.rs.html b/aardwolf-templates/templates/elements/icon.rs.html index d1e05528..29338376 100644 --- a/aardwolf-templates/templates/elements/icon.rs.html +++ b/aardwolf-templates/templates/elements/icon.rs.html @@ -1,3 +1,6 @@ -@(icon: &str) +@( + icon_class: &str +) + + - diff --git a/aardwolf-templates/templates/elements/input_checkbox.rs.html b/aardwolf-templates/templates/elements/input_checkbox.rs.html index 2d24bad1..85323973 100644 --- a/aardwolf-templates/templates/elements/input_checkbox.rs.html +++ b/aardwolf-templates/templates/elements/input_checkbox.rs.html @@ -1,13 +1,13 @@ @use crate::{InputCheckbox, templates::elements::icon}; -@(input: &InputCheckbox) +@(checkbox: &InputCheckbox)
-
+ diff --git a/aardwolf-templates/templates/elements/input_email.rs.html b/aardwolf-templates/templates/elements/input_email.rs.html index 9da8520b..f4ddccd7 100644 --- a/aardwolf-templates/templates/elements/input_email.rs.html +++ b/aardwolf-templates/templates/elements/input_email.rs.html @@ -1,5 +1,6 @@ -@use crate::{InputEmail, templates::elements::input}; +@use crate::templates::elements::input; @(input_email: &InputEmail) -@:input(&input_email.into()) +@:input(input_email) + diff --git a/aardwolf-templates/templates/elements/input_password_confirm.rs.html b/aardwolf-templates/templates/elements/input_password_confirm.rs.html index 6b4e49ed..3a5a3816 100644 --- a/aardwolf-templates/templates/elements/input_password_confirm.rs.html +++ b/aardwolf-templates/templates/elements/input_password_confirm.rs.html @@ -1,19 +1,6 @@ -@use gettext::Catalog; -@use gettext_macros::i18n; -@use crate::{elements::InputPasswordConfirm, templates::elements::input}; +@use crate::templates::elements::input; -@(input_password_confirm: &InputPasswordConfirm, catalog: &Catalog) +@(input_password_confirm: &InputPasswordConfirm) -@:input(&input_password_confirm.into()) +@:input(input_password_confirm) - -
- -
- - - - -
-
- diff --git a/aardwolf-templates/templates/elements/notification_content.rs.html b/aardwolf-templates/templates/elements/notification_content.rs.html index 3b3764eb..91432c52 100644 --- a/aardwolf-templates/templates/elements/notification_content.rs.html +++ b/aardwolf-templates/templates/elements/notification_content.rs.html @@ -5,21 +5,23 @@
-
-
- -
-
-
-
- - John Smith @aardwolf.social -
- @i18n!(notification_content.catalog, "Favorited your post") -
- - -
-
+
+
+ +
+
+
+
+

+ {{ notification_content.author_name }} + @{{ notification_content.author_handle }} +
+ {{ i18n!(notification_content.catalog, notification_content.message) }} +
+ +

+
+
+ diff --git a/aardwolf-templates/templates/elements/notification_dropdown.rs.html b/aardwolf-templates/templates/elements/notification_dropdown.rs.html index 7a17c775..0b4d6a9c 100644 --- a/aardwolf-templates/templates/elements/notification_dropdown.rs.html +++ b/aardwolf-templates/templates/elements/notification_dropdown.rs.html @@ -1,95 +1,42 @@ -@use gettext_macros::i18n; @use crate::elements::NotificationDropdown; +@use gettext_macros::i18n; -@(notification_dropdown: &NotificationDropdown) +@(notifications: &NotificationDropdown) - +
+ diff --git a/aardwolf-templates/templates/first_login.rs.html b/aardwolf-templates/templates/first_login.rs.html index e420bd7f..e235ea70 100644 --- a/aardwolf-templates/templates/first_login.rs.html +++ b/aardwolf-templates/templates/first_login.rs.html @@ -5,28 +5,30 @@ @(first_login: &FirstLogin) @:base(first_login.catalog, "Aardwolf | Get Posting", { -
+

@i18n!(first_login.catalog, "Get posting!")

- @i18n!(first_login.catalog, "Fill out your profile information") + @i18n!(first_login.catalog, "Fill out your profile information")
-
-
+
+ +
-
-
- @if let Some(ref a) = first_login.alert { - @:alert(a) - } - - @:input_text(&first_login.display_name) - @:input_text(&first_login.shortname) - @:input_select(&first_login.follow_policy) - @:input_select(&first_login.default_visibility) - @:input_checkbox(&first_login.is_searchable) - -
-
+
+
+ @if let Some(ref err) = first_login.alert { + @:alert(err) + } + + + @:input_text(&first_login.display_name) + @:input_text(&first_login.shortname) + @:input_select(&first_login.follow_policy) + @:input_select(&first_login.default_visibility) + @:input_checkbox(&first_login.is_searchable) + +
+
-
+ }); diff --git a/aardwolf-templates/templates/home/feed.rs.html b/aardwolf-templates/templates/home/feed.rs.html index c5a9c4b4..d991fc8f 100644 --- a/aardwolf-templates/templates/home/feed.rs.html +++ b/aardwolf-templates/templates/home/feed.rs.html @@ -1,69 +1,40 @@ -@use gettext_macros::i18n; @use crate::home::Feed; @(feed: &Feed)
-

- @i18n!(feed.catalog, + Profile picture

- Barbara Middleton -
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis porta eros lacus, nec ultricies elit blandit non. Suspendisse pellentesque mauris sit amet dolor blandit rutrum. Nunc in tempus turpis. -
- @i18n!(feed.catalog, "Like") · @i18n!(feed.catalog, "Reply") · @i18n!(feed.catalog, "Boost") · + John Doe +
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis porta eros lacus, nec ultricies elit blandit non. Suspendisse pellentesque mauris sit amet dolor blandit rutrum. Nunc in tempus turpis. +
+ Like · Reply · Boost ·

- @i18n!(feed.catalog, + Profile picture

- Sean Brown -
Donec sollicitudin urna eget eros malesuada sagittis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam blandit nisl a nulla sagittis, a lobortis leo feugiat. -
- @i18n!(feed.catalog, "Like") · @i18n!(feed.catalog, "Reply") · @i18n!(feed.catalog, "Boost") · -

-
- -
- Vivamus quis semper metus, non tincidunt dolor. Vivamus in mi eu lorem cursus ullamcorper sit amet nec massa. -
- -
- Morbi vitae diam et purus tincidunt porttitor vel vitae augue. Praesent malesuada metus sed pharetra euismod. Cras tellus odio, tincidunt iaculis diam non, porta aliquet tortor. -
-
-
- -
-
-

- @i18n!(feed.catalog, -

-
-
-
-

- Kayli Eunice -
Sed convallis scelerisque mauris, non pulvinar nunc mattis vel. Maecenas varius felis sit amet magna vestibulum euismod malesuada cursus libero. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia - Curae; Phasellus lacinia non nisl id feugiat. -
- @i18n!(feed.catalog, "Like") · @i18n!(feed.catalog, "Reply") · @i18n!(feed.catalog, "Boost") · + Jane Doe +
Donec sollicitudin urna eget eros malesuada sagittis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam blandit nisl a nulla sagittis, a lobortis leo feugiat. +
+ Like · Reply · Boost ·

- + diff --git a/aardwolf-templates/templates/home/home.rs.html b/aardwolf-templates/templates/home/home.rs.html index e77771b7..7a97fdac 100644 --- a/aardwolf-templates/templates/home/home.rs.html +++ b/aardwolf-templates/templates/home/home.rs.html @@ -1,30 +1,22 @@ @use crate::{ home::Home, - templates::{base, home::{feed, nav_top}, posts::{new_post}, asides::{shortcuts}} + templates::{base, home::nav_top, home::new_post, home::feed, asides::shortcuts}, }; -@(home: &Home) - -@:base(home.catalog, "Aardwolf | Home", { - @:nav_top(&home.nav_top) -
-
- - - @:shortcuts(&home.shortcuts) - -
-
-
- - - @:new_post(&home.new_post) - @:feed(&home.feed) - -
-
-
+@(home_data: &Home) + +@:base(home_data.catalog, "Aardwolf | Home", { + @:nav_top(&home_data.nav_top) +
+
+ @:shortcuts(&home_data.shortcuts) +
+
+
+ @:new_post(&home_data.new_post) + @:feed(&home_data.feed) +
+
+
}) - - diff --git a/aardwolf-templates/templates/home/nav_top.rs.html b/aardwolf-templates/templates/home/nav_top.rs.html index 9485d26e..5e82701c 100644 --- a/aardwolf-templates/templates/home/nav_top.rs.html +++ b/aardwolf-templates/templates/home/nav_top.rs.html @@ -1,67 +1,29 @@ -@use gettext_macros::i18n; @use crate::home::NavTop; -@(nav_top: &NavTop) +@(nav_top_data: &NavTop) + + + diff --git a/aardwolf-templates/templates/posts/new_post.rs.html b/aardwolf-templates/templates/posts/new_post.rs.html index c5bdbb54..9fa152fb 100644 --- a/aardwolf-templates/templates/posts/new_post.rs.html +++ b/aardwolf-templates/templates/posts/new_post.rs.html @@ -1,22 +1,14 @@ -@use gettext_macros::i18n; - -@use crate::{ - posts::NewPost, - templates::{elements::{alert, input_select, input_text, input_textarea}}, -}; - @(new_post: &NewPost) - -
+

- @new_post.username + @new_post.username

- @if let Some(ref a) = new_post.alert { - @:alert(a) + @if let Some(ref alert) = new_post.alert { + @:alert(alert) } @@ -26,7 +18,7 @@ @:input_select(&new_post.visibility); @:input_text(&new_post.name); - +
-
+
diff --git a/aardwolf-templates/templates/posts/reply_post.rs.html b/aardwolf-templates/templates/posts/reply_post.rs.html index 9fe1f242..f24d1ea6 100644 --- a/aardwolf-templates/templates/posts/reply_post.rs.html +++ b/aardwolf-templates/templates/posts/reply_post.rs.html @@ -1,27 +1,18 @@ -@use gettext_macros::i18n; - -@use crate::{ - posts::ReplyPost, - templates::{elements::{alert, input_select, input_text, input_textarea}}, -}; - @(reply_post: &ReplyPost) - -
+
-

- @reply_post.username -

+

+ @reply_post.username +

-
- @if let Some(ref a) = reply_post.alert { - @:alert(a) - } - - @:input_textarea(&reply_post.source) - @:input_select(&reply_post.visibility) - @:input_text(&reply_post.name) - -
- -
+
+ @if let Some(ref alert) = reply_post.alert { +
@:alert(alert)
+ } + + @:input_textarea(&reply_post.source) + @:input_select(&reply_post.visibility) + @:input_text(&reply_post.name) + +
+
diff --git a/aardwolf-types/Cargo.toml b/aardwolf-types/Cargo.toml index d2d15bd3..15debb3f 100644 --- a/aardwolf-types/Cargo.toml +++ b/aardwolf-types/Cargo.toml @@ -44,3 +44,7 @@ features = ["compat"] [dev-dependencies] aardwolf-test-helpers = { version = "0.1", path = "../aardwolf-test-helpers" } + +# Build script +[build] +script = "build.rs" \ No newline at end of file diff --git a/aardwolf-types/src/forms/personas/creation_form.rs b/aardwolf-types/src/forms/personas/creation_form.rs index 444a92a5..beb38af5 100644 --- a/aardwolf-types/src/forms/personas/creation_form.rs +++ b/aardwolf-types/src/forms/personas/creation_form.rs @@ -74,10 +74,14 @@ pub enum ValidateDisplayNameFail { } #[derive(Clone, Debug, Serialize)] -pub enum ValidateFollowPolicyFail {} +pub enum ValidateFollowPolicyFail { + Invalid, +} #[derive(Clone, Debug, Serialize)] -pub enum ValidateDefaultVisibilityFail {} +pub enum ValidateDefaultVisibilityFail { + Invalid, +} #[derive(Clone, Debug, Serialize)] pub enum ValidateShortnameFail { @@ -87,7 +91,10 @@ pub enum ValidateShortnameFail { } #[derive(Clone, Debug, Serialize)] -pub enum ValidateIsSearchableFail {} +pub enum ValidateIsSearchableFail { + Invalid, + SomeError, +} pub struct ValidatePersonaCreationForm(pub PersonaCreationForm); diff --git a/aardwolf-types/src/forms/posts.rs b/aardwolf-types/src/forms/posts.rs index 1d198691..7fcc83d2 100644 --- a/aardwolf-types/src/forms/posts.rs +++ b/aardwolf-types/src/forms/posts.rs @@ -9,105 +9,69 @@ use crate::{error::AardwolfFail, traits::Validate}; pub struct PostCreationForm { csrf_token: String, visibility: PostVisibility, - #[serde(default)] name: Option, source: String, } impl PostCreationForm { - pub fn as_state(&self) -> PostCreationFormState { + pub fn into_state(self) -> PostCreationFormState { PostCreationFormState { visibility: self.visibility, - name: self.name.clone(), - source: self.source.clone(), + name: self.name, + source: self.source, + username: String::new(), } } } +#[derive(Clone, Debug, Default)] pub struct PostCreationFormState { pub visibility: PostVisibility, pub name: Option, pub source: String, + pub username: String, } #[derive(Clone, Debug, Error, Serialize)] -#[error("Error validating post creation form")] -pub struct ValidatePostCreationFail { - pub visibility: Option, - pub source: Option, - pub name: Option, -} - -#[derive(Clone, Debug, Serialize)] -pub enum ValidateVisibilityError {} - -#[derive(Clone, Debug, Serialize, Error)] -pub enum ValidateSourceError { +pub enum ValidatePostCreationError { + #[error("Invalid visibility")] + InvalidVisibility, #[error("Source must not be empty")] - Empty, -} - -#[derive(Clone, Debug, Serialize)] -pub enum ValidateNameError {} - -impl ValidatePostCreationFail { - pub fn is_empty(&self) -> bool { - self.visibility.is_none() && self.source.is_none() && self.name.is_none() - } + EmptySource, + #[error("Name must not be empty")] + EmptyName, } -impl AardwolfFail for ValidatePostCreationFail {} +impl AardwolfFail for ValidatePostCreationError {} -pub struct ValidatePostCreationForm(pub PostCreationForm); +pub struct ValidatePostCreationForm(PostCreationForm); impl Validate for ValidatePostCreationForm { type Item = ValidatedPostCreationForm; - type Error = ValidatePostCreationFail; + type Error = ValidatePostCreationError; - fn validate(self) -> Result { - let mut err = ValidatePostCreationFail { - visibility: None, - source: None, - name: None, - }; - - let source = self.0.source.trim().to_owned(); - let content = source.clone(); // TODO: translate things here - let visibility = self.0.visibility; - let media_type = TEXT_HTML.into(); - - let name = if let Some(name) = self.0.name { - if name.trim().is_empty() { - None - } else { - Some(name) - } - } else { - None - }; - - if source.is_empty() { - err.source = Some(ValidateSourceError::Empty); + fn validate(&self) -> Result { + if self.0.source.is_empty() { + return Err(ValidatePostCreationError::EmptySource); } - if !err.is_empty() { - return Err(err); - } + let name = self.0.name.as_deref().map(|n| n.trim().to_string()).filter(|n| !n.is_empty()); Ok(ValidatedPostCreationForm { - media_type, - visibility, - content, - source, + media_type: TEXT_HTML, + visibility: self.0.visibility, + content: self.0.source.clone(), + source: self.0.source.clone(), name, }) } } +#[derive(Clone, Debug)] pub struct ValidatedPostCreationForm { - pub(crate) media_type: Mime, - pub(crate) visibility: PostVisibility, - pub(crate) content: String, - pub(crate) source: String, - pub(crate) name: Option, + pub media_type: Mime, + pub visibility: PostVisibility, + pub content: String, + pub source: String, + pub name: Option, } diff --git a/aardwolf-types/src/traits.rs b/aardwolf-types/src/traits.rs index 2667515c..22124ac5 100644 --- a/aardwolf-types/src/traits.rs +++ b/aardwolf-types/src/traits.rs @@ -17,7 +17,7 @@ mod default_impls { pub trait DbAction { type Item; - type Error: Fail; + type Error: std::error::Error; fn db_action(self, conn: &PgConnection) -> Result; } @@ -30,12 +30,13 @@ mod actix_web_impls { use diesel::PgConnection; use futures::future::{BoxFuture, FutureExt, TryFutureExt}; use r2d2::Pool; + use std::error::Error as StdError; use thiserror::Error; #[derive(Debug, Error)] pub enum DbActionError where - E: std::error::Error, + E: StdError, { #[error("Error in Db Action, {}", _0)] Error(#[source] E), @@ -49,16 +50,16 @@ mod actix_web_impls { impl From for DbActionError where - E: std::error::Error, + E: StdError, { - fn from(e: BlockingError) -> Self { - DbActionError::Canceled // TODO: Add actual handling for this + fn from(_: BlockingError) -> Self { + DbActionError::Canceled } } impl From for DbActionError where - E: std::error::Error, + E: StdError, { fn from(e: r2d2::Error) -> Self { DbActionError::Pool(e) @@ -67,7 +68,7 @@ mod actix_web_impls { pub trait DbAction { type Item: Send + 'static; - type Error: std::error::Error + Send; + type Error: StdError + Send; fn db_action(self, conn: &mut PgConnection) -> Result; @@ -78,17 +79,15 @@ mod actix_web_impls { where Self: Sized + Send + 'static, { - let result = block(move || -> Result> { + block(move || -> Result> { let conn = &mut *pool.get()?; self.db_action(conn).map_err(DbActionError::Error) }) - .map_err(DbActionError::from); - - // Flatten nested result - let result = result.map(|result| result.and_then(|inner| inner)); - - result.boxed() + .map_err(DbActionError::from) + .map(|result| result.and_then(|inner| inner)) + .boxed() } } } +