Refactored poem selection so that a static hashmap and vector are ceated as a prop that is passed to each component in order to grab poem data more efficiently and cleanly.
This commit is contained in:
parent
db2d86c5ee
commit
e593f46a35
@ -16,6 +16,7 @@ dioxus = "0.3.2"
|
|||||||
markdown = "1.0.0-alpha.7"
|
markdown = "1.0.0-alpha.7"
|
||||||
dioxus-ssr = "0.3.0"
|
dioxus-ssr = "0.3.0"
|
||||||
rust-embed = { version = "6.6.1" }
|
rust-embed = { version = "6.6.1" }
|
||||||
|
once_cell = "1.17.1"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
void-be = { path = "./void-be" }
|
void-be = { path = "./void-be" }
|
||||||
|
2
public/styles/tailwind.min.css
vendored
2
public/styles/tailwind.min.css
vendored
File diff suppressed because one or more lines are too long
@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
void-fe = { path = "../void-fe" }
|
void-fe = { path = "../void-fe" }
|
||||||
dioxus-ssr = { workspace = true }
|
dioxus-ssr = { workspace = true }
|
||||||
|
once_cell = { workspace = true }
|
||||||
|
|
||||||
# If you're unsure about why we're depending on a release candidate,
|
# If you're unsure about why we're depending on a release candidate,
|
||||||
# check the Rocket documentation:
|
# check the Rocket documentation:
|
||||||
|
@ -8,15 +8,17 @@ extern crate rocket;
|
|||||||
/// A module that handles the backend for the site.
|
/// A module that handles the backend for the site.
|
||||||
pub mod web_app_backend {
|
pub mod web_app_backend {
|
||||||
|
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
use rocket::fs::FileServer;
|
use rocket::fs::FileServer;
|
||||||
use rocket::http::{Cookie, CookieJar};
|
use rocket::http::{Cookie, CookieJar};
|
||||||
use rocket::response::Redirect;
|
use rocket::response::Redirect;
|
||||||
use rocket::{Build, Rocket};
|
use rocket::{Build, Rocket};
|
||||||
use rocket_dyn_templates::{context, Template};
|
use rocket_dyn_templates::{context, Template};
|
||||||
use void_fe::utils::prop_structs::PoemRequest;
|
use void_fe::utils::prop_structs::{PoemDatabase, VoidProps};
|
||||||
|
use void_fe::utils::user_prefs::*;
|
||||||
use void_fe::void_app::{self, VirtualDom};
|
use void_fe::void_app::{self, VirtualDom};
|
||||||
|
|
||||||
use void_fe::utils::user_prefs::*;
|
static POEM_DATABASE: OnceCell<PoemDatabase> = OnceCell::new();
|
||||||
|
|
||||||
async fn get_user_prefs(cookies: &CookieJar<'_>) -> UserPrefs {
|
async fn get_user_prefs(cookies: &CookieJar<'_>) -> UserPrefs {
|
||||||
let user_theme = match cookies.get("theme") {
|
let user_theme = match cookies.get("theme") {
|
||||||
@ -74,7 +76,15 @@ pub mod web_app_backend {
|
|||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn index(cookies: &CookieJar<'_>) -> Template {
|
async fn index(cookies: &CookieJar<'_>) -> Template {
|
||||||
let user_prefs = get_user_prefs(cookies).await;
|
let user_prefs = get_user_prefs(cookies).await;
|
||||||
let mut vdom = VirtualDom::new_with_props(void_app::HomePage, user_prefs);
|
let void_props = VoidProps {
|
||||||
|
slug: None,
|
||||||
|
poem_database: POEM_DATABASE
|
||||||
|
.get()
|
||||||
|
.expect("Poem database is not initialized")
|
||||||
|
.clone(),
|
||||||
|
user_prefs: user_prefs,
|
||||||
|
};
|
||||||
|
let mut vdom = VirtualDom::new_with_props(void_app::HomePage, void_props);
|
||||||
let _ = vdom.rebuild();
|
let _ = vdom.rebuild();
|
||||||
let output = dioxus_ssr::render(&vdom);
|
let output = dioxus_ssr::render(&vdom);
|
||||||
Template::render(
|
Template::render(
|
||||||
@ -120,7 +130,15 @@ pub mod web_app_backend {
|
|||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn poem_list(cookies: &CookieJar<'_>) -> Template {
|
async fn poem_list(cookies: &CookieJar<'_>) -> Template {
|
||||||
let user_prefs = get_user_prefs(cookies).await;
|
let user_prefs = get_user_prefs(cookies).await;
|
||||||
let mut vdom = VirtualDom::new_with_props(void_app::PoemListPage, user_prefs);
|
let void_props = VoidProps {
|
||||||
|
slug: None,
|
||||||
|
poem_database: POEM_DATABASE
|
||||||
|
.get()
|
||||||
|
.expect("Poem database is not initialized")
|
||||||
|
.clone(),
|
||||||
|
user_prefs: user_prefs,
|
||||||
|
};
|
||||||
|
let mut vdom = VirtualDom::new_with_props(void_app::PoemListPage, void_props);
|
||||||
let _ = vdom.rebuild();
|
let _ = vdom.rebuild();
|
||||||
let output = dioxus_ssr::render(&vdom);
|
let output = dioxus_ssr::render(&vdom);
|
||||||
Template::render(
|
Template::render(
|
||||||
@ -137,13 +155,15 @@ pub mod web_app_backend {
|
|||||||
#[get("/<entry>")]
|
#[get("/<entry>")]
|
||||||
async fn poem(cookies: &CookieJar<'_>, entry: &str) -> Template {
|
async fn poem(cookies: &CookieJar<'_>, entry: &str) -> Template {
|
||||||
let user_prefs = get_user_prefs(cookies).await;
|
let user_prefs = get_user_prefs(cookies).await;
|
||||||
let mut vdom = VirtualDom::new_with_props(
|
let void_props = VoidProps {
|
||||||
void_app::PoemPage,
|
slug: Some(entry.to_string()),
|
||||||
PoemRequest {
|
poem_database: POEM_DATABASE
|
||||||
slug: format!("{entry}"),
|
.get()
|
||||||
user_prefs,
|
.expect("Poem database is not initialized")
|
||||||
},
|
.clone(),
|
||||||
);
|
user_prefs: user_prefs,
|
||||||
|
};
|
||||||
|
let mut vdom = VirtualDom::new_with_props(void_app::PoemPage, void_props);
|
||||||
let _ = vdom.rebuild();
|
let _ = vdom.rebuild();
|
||||||
let output = dioxus_ssr::render(&vdom);
|
let output = dioxus_ssr::render(&vdom);
|
||||||
Template::render(
|
Template::render(
|
||||||
@ -159,6 +179,9 @@ pub mod web_app_backend {
|
|||||||
|
|
||||||
/// This runs `rocket::build()` with the needed mounts and routes.
|
/// This runs `rocket::build()` with the needed mounts and routes.
|
||||||
pub async fn build_rocket() -> Rocket<Build> {
|
pub async fn build_rocket() -> Rocket<Build> {
|
||||||
|
let mut poem_database = PoemDatabase::new();
|
||||||
|
poem_database.build_poem_database().await;
|
||||||
|
POEM_DATABASE.set(poem_database).expect("Could not initialize poem database.");
|
||||||
rocket::build()
|
rocket::build()
|
||||||
.mount("/images", FileServer::from("public/images"))
|
.mount("/images", FileServer::from("public/images"))
|
||||||
.mount("/styles", FileServer::from("public/styles"))
|
.mount("/styles", FileServer::from("public/styles"))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# im on repeat
|
# im on repeat
|
||||||
[Audio reading](https://cloud.werefox.dev/s/dq5ccm5QqmMF4GB)
|
*Author's note: Unfortunately, I've lost the audio reading for this.*
|
||||||
|
|
||||||
Death is like a memory. Ceaseless, and comforting\
|
Death is like a memory. Ceaseless, and comforting\
|
||||||
Knowing things will end has always helped me feel like I'm free\
|
Knowing things will end has always helped me feel like I'm free\
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Iced Coffee
|
# Iced Coffee
|
||||||
[Listen to the song on Soundcloud](https://soundcloud.com/alexis-werefox/iced-coffee/s-5SgBwPrLwyR)
|
<a href="https://soundcloud.com/alexis-werefox/iced-coffee/s-5SgBwPrLwyR">Listen to the song on Soundcloud</a>
|
||||||
|
|
||||||
*Iced coffee on a cold Winter's day* \
|
*Iced coffee on a cold Winter's day* \
|
||||||
*Iced coffee bittersweet at the taste* \
|
*Iced coffee bittersweet at the taste* \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use crate::{components::void_buttons::NavigationButton, utils::user_prefs::{UserPrefs, ThemedComponent}};
|
use crate::{components::void_buttons::{ButtonGroup, NavigationButton}, utils::user_prefs::{UserPrefs, ThemedComponent}};
|
||||||
|
|
||||||
pub fn Footer(cx: Scope<UserPrefs>) -> Element {
|
pub fn Footer(cx: Scope<UserPrefs>) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
@ -13,7 +13,12 @@ fn MutantStandardFooter(cx: Scope<UserPrefs>) -> Element {
|
|||||||
let user_font = cx.props.get_font_class();
|
let user_font = cx.props.get_font_class();
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
div { class: "p-4 flex flex-col space-y-4 mx-auto max-w-full justify-center ring-4 {user_theme} {user_font}",
|
div { class: "p-4 flex flex-col space-y-4 mx-auto max-w-full justify-center ring-4 {user_theme} {user_font}",
|
||||||
NavigationButton { title: "⚙️ Settings".to_string(), slug: "/settings".to_string(), user_prefs: user_prefs }
|
ButtonGroup{
|
||||||
|
NavigationButton { title: "⚙️ Settings".to_string(), slug: "/settings".to_string(), user_prefs: user_prefs.clone() }
|
||||||
|
span { class: "font-nerd contents",
|
||||||
|
NavigationButton { title: " /src".to_string(), slug: "https://gitea.werefox.cafe/ada/void-werefox-cafe".to_string(), user_prefs: user_prefs }
|
||||||
|
}
|
||||||
|
}
|
||||||
div { class: "flex mx-auto max-w-full justify-center text-md text-center",
|
div { class: "flex mx-auto max-w-full justify-center text-md text-center",
|
||||||
"This site uses Mutant Standard emoji, which are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License"
|
"This site uses Mutant Standard emoji, which are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License"
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,9 @@ use dioxus::prelude::*;
|
|||||||
|
|
||||||
pub fn PageBase<'a>(cx: Scope<'a, PageChildren<'a>>) -> Element {
|
pub fn PageBase<'a>(cx: Scope<'a, PageChildren<'a>>) -> Element {
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
|
a { rel: "me", href: "https://yiff.life/@werefox", hidden: true, "Mastodon" }
|
||||||
div { class: "min-h-screen",
|
div { class: "min-h-screen",
|
||||||
div { class: "container space-y-4 mx-auto p-4",
|
div { class: "container space-y-4 mx-auto p-4", &cx.props.children }
|
||||||
&cx.props.children
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
use crate::components::void_buttons::*;
|
use crate::components::void_buttons::*;
|
||||||
use crate::components::void_title::*;
|
use crate::components::void_title::*;
|
||||||
use crate::utils::{helpers, prop_structs::{PoemChildren, PoemData}, user_prefs::{UserPrefs, ThemedComponent} };
|
use crate::utils::prop_structs::VoidProps;
|
||||||
|
use crate::utils::{prop_structs::PoemChildren, user_prefs::ThemedComponent};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
pub fn PoemList(cx: Scope<UserPrefs>) -> Element {
|
pub fn PoemList(cx: Scope<VoidProps>) -> Element {
|
||||||
let poem_list = helpers::get_poem_list();
|
let poem_list = cx.props.poem_database.get_poem_list();
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
ul { class: "flex flex-col space-y-4",
|
ul { class: "flex flex-col space-y-4",
|
||||||
poem_list.into_iter().map(|p| {
|
poem_list.into_iter().map(|p| {
|
||||||
let user_prefs = cx.props.clone();
|
let slug = format!("/poems/{}", p.0);
|
||||||
let slug = format!("/poems/{}", p.1);
|
|
||||||
rsx!{
|
rsx!{
|
||||||
NavigationButton { title: p.0, slug: slug, user_prefs: user_prefs.clone() }
|
NavigationButton { title: p.1, slug: slug, user_prefs: cx.props.user_prefs.clone() }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -26,25 +26,41 @@ pub fn MakePoem<'a>(cx: Scope<'a, PoemChildren<'a>>) -> Element {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetPoem(cx: Scope<PoemData>) -> Element {
|
pub fn GetPoem(cx: Scope<VoidProps>) -> Element {
|
||||||
let slug = String::from(cx.props.slug.clone().expect("No slug specified."));
|
let poem_database = &cx.props.poem_database;
|
||||||
let (title, content, creation_date) = helpers::get_poem(slug.clone());
|
let slug = String::from(&cx.props.slug.clone().expect("No slug specified."));
|
||||||
|
let poem_struct = poem_database.get_poem(slug.clone());
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
Title { title: title, is_html: true, user_prefs: cx.props.user_prefs.clone() }
|
Title { title: poem_struct.title.clone(), is_html: true, user_prefs: cx.props.user_prefs.clone() }
|
||||||
MakePoem{
|
MakePoem{
|
||||||
PoemContent { content: content, creation_date: creation_date, user_prefs: cx.props.user_prefs.clone() }
|
PoemContent { slug: slug, poem_database: poem_database.clone(), user_prefs: cx.props.user_prefs.clone() }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn PoemContent(cx: Scope<PoemData>) -> Element {
|
pub fn PoemContent(cx: Scope<VoidProps>) -> Element {
|
||||||
let (user_theme, user_font) = cx.props.user_prefs.get_pref_classes(ThemedComponent::Card);
|
let (user_theme, user_font) = cx.props.user_prefs.get_pref_classes(ThemedComponent::Card);
|
||||||
let content = cx.props.content.clone().expect("No content specified.");
|
let slug = cx
|
||||||
let creation_date = cx
|
|
||||||
.props
|
.props
|
||||||
|
.slug
|
||||||
|
.as_ref()
|
||||||
|
.expect("Received slug for poem selection.");
|
||||||
|
let content = &cx
|
||||||
|
.props
|
||||||
|
.poem_database
|
||||||
|
.poem_hashmap
|
||||||
|
.get(slug)
|
||||||
|
.expect("Grabbed poem stuct from databse.")
|
||||||
|
.content
|
||||||
|
.clone();
|
||||||
|
let creation_date = &cx
|
||||||
|
.props
|
||||||
|
.poem_database
|
||||||
|
.poem_hashmap
|
||||||
|
.get(slug)
|
||||||
|
.expect("Grabbed poem struct from database.")
|
||||||
.creation_date
|
.creation_date
|
||||||
.clone()
|
.clone();
|
||||||
.expect("No creation date specified.");
|
|
||||||
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
||||||
return cx.render(rsx! {
|
return cx.render(rsx! {
|
||||||
div { class: "flex p-2 mx-auto max-w-full justify-center",
|
div { class: "flex p-2 mx-auto max-w-full justify-center",
|
||||||
|
@ -62,19 +62,20 @@ pub mod void_app {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Renders the app and returns the rendered Element.
|
/// Renders the app and returns the rendered Element.
|
||||||
pub fn HomePage(cx: Scope<UserPrefs>) -> Element {
|
pub fn HomePage(cx: Scope<VoidProps>) -> Element {
|
||||||
let user_prefs = cx.props.clone();
|
let poem_database = &cx.props.poem_database;
|
||||||
|
let user_prefs = cx.props.user_prefs.clone();
|
||||||
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
|
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
|
||||||
let title = "A Letter to the Void".to_string();
|
let page_title = "A Letter to the Void".to_string();
|
||||||
cx.render(rsx!{
|
cx.render(rsx!{
|
||||||
div { class: "{user_theme} {user_font}",
|
div { class: "{user_theme} {user_font}",
|
||||||
PageBase {
|
PageBase {
|
||||||
Title { title: title, is_html: false, user_prefs: user_prefs.clone() }
|
Title { title: page_title, is_html: false, user_prefs: user_prefs.clone() }
|
||||||
RenderContent { content: helpers::get_homepage_paragraph(), user_prefs: user_prefs.clone() }
|
RenderContent { content: helpers::get_homepage_paragraph(), user_prefs: user_prefs.clone() }
|
||||||
ButtonGroup {
|
ButtonGroup {
|
||||||
NavigationButton { title: "See Latest Entry".to_string(), slug: helpers::get_latest_entry("".to_string()), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "See Latest Entry".to_string(), slug: poem_database.get_latest_entry("".to_string()), user_prefs: user_prefs.clone() }
|
||||||
NavigationButton { title: "See Oldest Entry".to_string(), slug: helpers::get_oldest_entry("".to_string()), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "See Oldest Entry".to_string(), slug: poem_database.get_oldest_entry("".to_string()), user_prefs: user_prefs.clone() }
|
||||||
NavigationButton { title: "See A Random Entry".to_string(), slug: helpers::get_random_entry(), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "See A Random Entry".to_string(), slug: poem_database.get_random_entry(), user_prefs: user_prefs.clone() }
|
||||||
NavigationButton { title: "See All Entries".to_string(), slug: "/poems".to_string(), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "See All Entries".to_string(), slug: "/poems".to_string(), user_prefs: user_prefs.clone() }
|
||||||
}
|
}
|
||||||
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
|
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
|
||||||
@ -84,15 +85,16 @@ pub mod void_app {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Renders the app and returns the rendered Element.
|
/// Renders the app and returns the rendered Element.
|
||||||
pub fn PoemListPage(cx: Scope<UserPrefs>) -> Element {
|
pub fn PoemListPage(cx: Scope<VoidProps>) -> Element {
|
||||||
let user_prefs = cx.props.clone();
|
let poem_database = &cx.props.poem_database;
|
||||||
|
let user_prefs = cx.props.user_prefs.clone();
|
||||||
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
|
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div { class: "{user_theme} {user_font}",
|
div { class: "{user_theme} {user_font}",
|
||||||
PageBase {
|
PageBase {
|
||||||
Title { title: "A Letter to the Void".to_string(), is_html: false, user_prefs: user_prefs.clone() }
|
Title { title: "A Letter to the Void".to_string(), is_html: false, user_prefs: user_prefs.clone() }
|
||||||
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
||||||
PoemList { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
PoemList { poem_database: poem_database.clone(), user_prefs: user_prefs.clone() }
|
||||||
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
||||||
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
|
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
|
||||||
}
|
}
|
||||||
@ -100,11 +102,12 @@ pub mod void_app {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn PoemPage(cx: Scope<PoemRequest>) -> Element {
|
pub fn PoemPage(cx: Scope<VoidProps>) -> Element {
|
||||||
|
let poem_database = &cx.props.poem_database;
|
||||||
let user_prefs = cx.props.user_prefs.clone();
|
let user_prefs = cx.props.user_prefs.clone();
|
||||||
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
|
let (user_theme, user_font) = user_prefs.get_pref_classes(ThemedComponent::Page);
|
||||||
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
#[cfg(any(target_family = "unix", target_family = "windows"))]
|
||||||
let slug = cx.props.slug.clone();
|
let slug = &cx.props.slug.as_ref().expect("A slug was given in the pops.").clone();
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
let slug = String::from(
|
let slug = String::from(
|
||||||
dioxus_router::use_route(cx)
|
dioxus_router::use_route(cx)
|
||||||
@ -115,13 +118,13 @@ pub mod void_app {
|
|||||||
div { class: "{user_theme} {user_font}",
|
div { class: "{user_theme} {user_font}",
|
||||||
PageBase {
|
PageBase {
|
||||||
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
||||||
GetPoem { slug: slug.clone(), user_prefs: user_prefs.clone() }
|
GetPoem { slug: slug.clone(), poem_database: poem_database.clone(), user_prefs: user_prefs.clone() }
|
||||||
ButtonGroup {
|
ButtonGroup {
|
||||||
NavigationButton { title: "Oldest".to_string(), slug: helpers::get_oldest_entry(slug.clone()), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "Oldest".to_string(), slug: poem_database.get_oldest_entry(slug.clone()), user_prefs: user_prefs.clone() }
|
||||||
NavigationButton { title: "Previous".to_string(), slug: helpers::get_previous_entry(slug.clone()), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "Previous".to_string(), slug: poem_database.get_previous_entry(slug.clone()), user_prefs: user_prefs.clone() }
|
||||||
NavigationButton { title: "Random".to_string(), slug: helpers::get_random_entry(), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "Random".to_string(), slug: poem_database.get_random_entry(), user_prefs: user_prefs.clone() }
|
||||||
NavigationButton { title: "Next".to_string(), slug: helpers::get_next_entry(slug.clone()), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "Next".to_string(), slug: poem_database.get_next_entry(slug.clone()), user_prefs: user_prefs.clone() }
|
||||||
NavigationButton { title: "Latest".to_string(), slug: helpers::get_latest_entry(slug.clone()), user_prefs: user_prefs.clone() }
|
NavigationButton { title: "Latest".to_string(), slug: poem_database.get_latest_entry(slug.clone()), user_prefs: user_prefs.clone() }
|
||||||
}
|
}
|
||||||
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
BackToHomePage { theme: user_prefs.clone().get_theme(), font: user_prefs.clone().get_font() }
|
||||||
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
|
Footer { theme: user_prefs.clone().get_theme(), font: user_prefs.get_font() }
|
||||||
|
@ -1,91 +1,105 @@
|
|||||||
use markdown::Options;
|
use markdown::Options;
|
||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
use rust_embed::RustEmbed;
|
use rust_embed::RustEmbed;
|
||||||
use std::collections::VecDeque;
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
|
use super::prop_structs::{PoemDatabase, PoemStruct};
|
||||||
#[derive(RustEmbed)]
|
#[derive(RustEmbed)]
|
||||||
#[folder = "data/other"]
|
#[folder = "data/other"]
|
||||||
struct OtherData;
|
struct OtherData;
|
||||||
|
|
||||||
#[derive(RustEmbed)]
|
#[derive(RustEmbed)]
|
||||||
#[folder = "data/poems"]
|
#[folder = "data/poems"]
|
||||||
struct Poems;
|
pub struct Poems;
|
||||||
|
|
||||||
pub fn get_homepage_paragraph() -> String {
|
impl PoemDatabase {
|
||||||
let homepage_paragraph_content =
|
pub fn new() -> PoemDatabase {
|
||||||
OtherData::get("homepage.md").expect("Found homepage paragraph.");
|
PoemDatabase {
|
||||||
let homepage_paragraph_to_string =
|
poem_list: Vec::<(String, String)>::new(),
|
||||||
std::str::from_utf8(homepage_paragraph_content.data.as_ref())
|
poem_hashmap: HashMap::<String, PoemStruct>::new(),
|
||||||
.expect("Homepage file is valid UTF-8");
|
}
|
||||||
let test =
|
|
||||||
markdown::to_html_with_options(homepage_paragraph_to_string, &Options::gfm()).unwrap();
|
|
||||||
test
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_poem(slug: String) -> (String, String, String) {
|
// There's no need to actually make a database yet, but maybe in the future...
|
||||||
let filename = String::from(String::from(slug.clone()) + ".md");
|
pub async fn build_poem_database(&mut self) {
|
||||||
let creation_date =
|
for p in Poems::iter() {
|
||||||
String::from(String::from("<br>Written on: ") + filename.split("_").next().unwrap());
|
let filename = p.to_string();
|
||||||
let poem_content = Poems::get(&filename).expect("Found poem {filename:?}");
|
let poem_content = Poems::get(&filename).expect("Found poem {filename:?}");
|
||||||
let mut poem_to_str = std::str::from_utf8(poem_content.data.as_ref())
|
let mut poem_to_str = std::str::from_utf8(poem_content.data.as_ref())
|
||||||
.expect("Title is valid UT8.")
|
.expect("Poem is valid UT8.")
|
||||||
.lines();
|
.lines();
|
||||||
let poem_title = poem_to_str.next().unwrap();
|
let poem_title = poem_to_str.next().expect("No title specified.");
|
||||||
let poem_content = poem_to_str.into_iter().collect::<Vec<&str>>().join("\n");
|
let poem_content = poem_to_str.into_iter().collect::<Vec<&str>>().join("\n");
|
||||||
let poem_title_to_html_string =
|
let poem_title_to_html_string =
|
||||||
markdown::to_html_with_options(poem_title, &Options::gfm()).unwrap();
|
markdown::to_html_with_options(poem_title, &Options::gfm()).unwrap();
|
||||||
let poem_content_to_html_string =
|
let poem_content_to_html_string =
|
||||||
markdown::to_html_with_options(poem_content.as_str(), &Options::gfm()).unwrap();
|
markdown::to_html_with_options(poem_content.as_str(), &Options::gfm()).unwrap();
|
||||||
|
let mut split_filename = filename.trim_end_matches(".md").split("_");
|
||||||
|
let creation_date = split_filename.next().expect("Obtained creation date");
|
||||||
|
let slug = split_filename.next().expect("Obtained slug");
|
||||||
|
self.poem_list
|
||||||
|
.push((creation_date.to_string(), slug.to_string()));
|
||||||
|
let poem_struct = PoemStruct {
|
||||||
|
title: poem_title_to_html_string.to_string(),
|
||||||
|
content: poem_content_to_html_string,
|
||||||
|
creation_date: creation_date.to_string(),
|
||||||
|
};
|
||||||
|
self.poem_hashmap.insert(slug.to_string(), poem_struct);
|
||||||
|
}
|
||||||
|
self.poem_list.sort_by_key(|k| k.0.clone())
|
||||||
|
}
|
||||||
|
pub fn get_poem(&self, slug: String) -> PoemStruct {
|
||||||
|
self.poem_hashmap
|
||||||
|
.get(slug.as_str())
|
||||||
|
.expect("Grabbed poem from database")
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_poem_list(&self) -> Vec<(String, String)> {
|
||||||
|
self.poem_list
|
||||||
|
.iter()
|
||||||
|
.map(|s| {
|
||||||
(
|
(
|
||||||
poem_title_to_html_string,
|
s.1.clone(),
|
||||||
poem_content_to_html_string,
|
self.poem_hashmap
|
||||||
creation_date,
|
.get(&s.1)
|
||||||
|
.expect("Got poemstruct from database")
|
||||||
|
.title
|
||||||
|
.clone(),
|
||||||
)
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<(String, String)>>()
|
||||||
|
.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_poem_list() -> Vec<(String, String)> {
|
pub fn get_oldest_entry(&self, current: String) -> String {
|
||||||
let mut poem_list = Vec::new();
|
let mut poem_list = VecDeque::from_iter(self.poem_list.iter());
|
||||||
for p in Poems::iter() {
|
|
||||||
let filename = p.to_string();
|
|
||||||
let poem_content = Poems::get(&filename).expect("Found poem {filename:?}");
|
|
||||||
let mut poem_to_str = std::str::from_utf8(poem_content.data.as_ref())
|
|
||||||
.expect("Title is valid UT8.")
|
|
||||||
.lines();
|
|
||||||
let title_markdown = poem_to_str.next().expect("No title specified.");
|
|
||||||
let title = markdown::to_html_with_options(title_markdown, &Options::gfm()).unwrap();
|
|
||||||
let slug = String::from(filename.trim_end_matches(".md"));
|
|
||||||
poem_list.push((title.clone(), slug.clone()));
|
|
||||||
}
|
|
||||||
log::trace!("{poem_list:?}");
|
|
||||||
poem_list
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_oldest_entry(current: String) -> String {
|
|
||||||
let mut poem_list = VecDeque::from(get_poem_list());
|
|
||||||
let oldest = poem_list
|
let oldest = poem_list
|
||||||
.pop_front()
|
.pop_front()
|
||||||
.expect("There is an entry in this list of poems.")
|
.expect("There is an entry in this list of poems.")
|
||||||
.1;
|
.1
|
||||||
|
.clone();
|
||||||
if current == oldest {
|
if current == oldest {
|
||||||
return format!("/poems/{current}#");
|
return format!("/poems/{current}#");
|
||||||
}
|
}
|
||||||
format!("/poems/{oldest}")
|
format!("/poems/{oldest}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_latest_entry(current: String) -> String {
|
pub fn get_latest_entry(&self, current: String) -> String {
|
||||||
let mut poem_list = get_poem_list();
|
let mut poem_list = self.poem_list.clone();
|
||||||
let latest = poem_list
|
let latest = poem_list
|
||||||
.pop()
|
.pop()
|
||||||
.expect("There is an entry in this list of poems.")
|
.expect("There is an entry in this list of poems.")
|
||||||
.1;
|
.1
|
||||||
|
.clone();
|
||||||
if current == latest {
|
if current == latest {
|
||||||
return format!("/poems/{current}#");
|
return format!("/poems/{current}#");
|
||||||
}
|
}
|
||||||
format!("/poems/{latest}")
|
format!("/poems/{latest}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_previous_entry(current: String) -> String {
|
pub fn get_previous_entry(&self, current: String) -> String {
|
||||||
let poem_list = get_poem_list();
|
let poem_list = self.poem_list.clone();
|
||||||
match poem_list.iter().enumerate().find_map(|(index, p)| {
|
match poem_list.iter().enumerate().find_map(|(index, p)| {
|
||||||
if p.1 == current {
|
if p.1 == current {
|
||||||
if index != 0 {
|
if index != 0 {
|
||||||
@ -102,8 +116,8 @@ pub fn get_previous_entry(current: String) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_next_entry(current: String) -> String {
|
pub fn get_next_entry(&self, current: String) -> String {
|
||||||
let poem_list = get_poem_list();
|
let poem_list = self.poem_list.clone();
|
||||||
match poem_list.iter().enumerate().find_map(|(index, p)| {
|
match poem_list.iter().enumerate().find_map(|(index, p)| {
|
||||||
if p.1 == current {
|
if p.1 == current {
|
||||||
if index != poem_list.len() - 1 {
|
if index != poem_list.len() - 1 {
|
||||||
@ -120,8 +134,8 @@ pub fn get_next_entry(current: String) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_random_entry() -> String {
|
pub fn get_random_entry(&self) -> String {
|
||||||
let poem_list = get_poem_list();
|
let poem_list = self.poem_list.clone();
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let random_entry = poem_list
|
let random_entry = poem_list
|
||||||
.choose(&mut rng)
|
.choose(&mut rng)
|
||||||
@ -130,3 +144,15 @@ pub fn get_random_entry() -> String {
|
|||||||
.clone();
|
.clone();
|
||||||
format!("/poems/{random_entry}")
|
format!("/poems/{random_entry}")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_homepage_paragraph() -> String {
|
||||||
|
let homepage_paragraph_content =
|
||||||
|
OtherData::get("homepage.md").expect("Found homepage paragraph.");
|
||||||
|
let homepage_paragraph_to_string =
|
||||||
|
std::str::from_utf8(homepage_paragraph_content.data.as_ref())
|
||||||
|
.expect("Homepage file is valid UTF-8");
|
||||||
|
let test =
|
||||||
|
markdown::to_html_with_options(homepage_paragraph_to_string, &Options::gfm()).unwrap();
|
||||||
|
test
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
use crate::void_app::{Element, Props};
|
use crate::void_app::{Element, Props};
|
||||||
|
|
||||||
use super::user_prefs::UserPrefs;
|
use super::user_prefs::UserPrefs;
|
||||||
|
|
||||||
#[derive(PartialEq, Props)]
|
#[derive(PartialEq, Props)]
|
||||||
@ -29,14 +29,25 @@ pub struct ButtonProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Props)]
|
#[derive(PartialEq, Props)]
|
||||||
pub struct PoemData {
|
pub struct VoidProps {
|
||||||
pub title: Option<String>,
|
|
||||||
pub content: Option<String>,
|
|
||||||
pub creation_date: Option<String>,
|
|
||||||
pub slug: Option<String>,
|
pub slug: Option<String>,
|
||||||
|
pub poem_database: PoemDatabase,
|
||||||
pub user_prefs: UserPrefs,
|
pub user_prefs: UserPrefs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Props, Clone, Debug)]
|
||||||
|
pub struct PoemDatabase {
|
||||||
|
pub poem_list: Vec<(String, String)>,
|
||||||
|
pub poem_hashmap: HashMap<String, PoemStruct>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
pub struct PoemStruct {
|
||||||
|
pub title: String,
|
||||||
|
pub content: String,
|
||||||
|
pub creation_date: String,
|
||||||
|
}
|
||||||
|
|
||||||
// These next three should all just be one prop.
|
// These next three should all just be one prop.
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
pub struct PoemChildren<'a> {
|
pub struct PoemChildren<'a> {
|
||||||
|
Loading…
Reference in New Issue
Block a user