2025-01-25 14:30:08 +01:00
|
|
|
use dioxus::prelude::*;
|
|
|
|
|
|
|
|
use crate::domain::entities::site::{Block, PageContent, Post};
|
|
|
|
|
2025-01-25 15:21:38 +01:00
|
|
|
use super::{meta, server::get_posts};
|
2025-01-25 14:30:08 +01:00
|
|
|
|
|
|
|
#[component]
|
|
|
|
pub fn Page() -> Element {
|
|
|
|
let page = meta::page();
|
|
|
|
let info = page.data.info;
|
|
|
|
|
|
|
|
rsx! {
|
|
|
|
h2 { "Page {info.title}" }
|
|
|
|
match page.data.content {
|
|
|
|
PageContent::Single { content } => rsx! {
|
|
|
|
PostElement { post: content }
|
|
|
|
},
|
|
|
|
PageContent::Collection { kind: _, collection_id } => {
|
|
|
|
rsx! {
|
|
|
|
SuspenseBoundary { fallback: |_context: SuspenseContext| rsx! { "..." },
|
2025-01-25 15:21:38 +01:00
|
|
|
Collection { collection_id }
|
2025-01-25 14:30:08 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[component]
|
|
|
|
pub fn Collection(collection_id: String) -> Element {
|
|
|
|
let site = meta::site();
|
|
|
|
let posts =
|
|
|
|
use_server_future(move || get_posts(site.info.domain.clone(), collection_id.clone()))?
|
|
|
|
.suspend()?;
|
|
|
|
|
|
|
|
let result = match &*posts.read() {
|
|
|
|
Ok(posts) => rsx! {
|
|
|
|
for post in posts.data.clone() {
|
|
|
|
PostElement { post }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
rsx! {
|
|
|
|
h1 { "FATAL ERROR: {err}" }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
result
|
2025-01-25 15:21:38 +01:00
|
|
|
}
|
2025-01-25 14:30:08 +01:00
|
|
|
|
|
|
|
#[component]
|
|
|
|
pub fn PostElement(post: Post) -> Element {
|
|
|
|
rsx! {
|
|
|
|
for block in post.blocks {
|
|
|
|
BlockElement { block }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[component]
|
|
|
|
pub fn BlockElement(block: Block) -> Element {
|
|
|
|
match block {
|
|
|
|
Block::Text { text } => rsx! {
|
|
|
|
p { "{text}" }
|
|
|
|
},
|
|
|
|
Block::Gallery { images } => rsx! {
|
|
|
|
for image in images {
|
|
|
|
img { src: "{image.src}", alt: "{image.caption}" }
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2025-01-26 13:25:24 +01:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use meta::SiteContext;
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
domain::entities::{
|
|
|
|
cursor::Paginated,
|
|
|
|
site::{Image, SiteInfo},
|
|
|
|
},
|
|
|
|
outbound::services::site::{MockSiteService, SiteServiceProvider},
|
|
|
|
};
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn block_renders_text() {
|
|
|
|
let text = "Hello, world!";
|
|
|
|
let block = Block::Text {
|
|
|
|
text: text.to_string(),
|
|
|
|
};
|
|
|
|
let element = rsx! {
|
|
|
|
BlockElement { block }
|
|
|
|
};
|
|
|
|
let elem_str = dioxus::ssr::render_element(element);
|
|
|
|
assert!(elem_str.contains(text));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn block_gallery_renders_images() {
|
|
|
|
let images = vec![
|
|
|
|
Image {
|
|
|
|
src: "https://example.com/image1.jpg".to_string(),
|
|
|
|
caption: "Image 1".to_string(),
|
|
|
|
},
|
|
|
|
Image {
|
|
|
|
src: "https://example.com/image2.jpg".to_string(),
|
|
|
|
caption: "Image 2".to_string(),
|
|
|
|
},
|
|
|
|
];
|
|
|
|
let block = Block::Gallery { images };
|
|
|
|
let element = rsx! {
|
|
|
|
BlockElement { block }
|
|
|
|
};
|
|
|
|
let elem_str = dioxus::ssr::render_element(element);
|
|
|
|
assert!(elem_str.contains("<img"));
|
|
|
|
assert!(elem_str.contains("https://example.com/image1.jpg"));
|
|
|
|
assert!(elem_str.contains("https://example.com/image2.jpg"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn post_renders_blocks() {
|
|
|
|
let blocks = vec![
|
|
|
|
Block::Text {
|
|
|
|
text: "Hello, world!".to_string(),
|
|
|
|
},
|
|
|
|
Block::Text {
|
|
|
|
text: "Something else!".to_string(),
|
|
|
|
},
|
|
|
|
];
|
|
|
|
let post = Post { blocks };
|
|
|
|
let element = rsx! {
|
|
|
|
PostElement { post }
|
|
|
|
};
|
|
|
|
let elem_str = dioxus::ssr::render_element(element);
|
|
|
|
assert!(elem_str.contains("Hello, world!"));
|
|
|
|
assert!(elem_str.contains("Something else!"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn collection_renders_posts() {
|
|
|
|
let mut app = VirtualDom::new(|| {
|
|
|
|
rsx! {
|
|
|
|
Collection { collection_id: "".to_string() }
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
app.provide_root_context(SiteContext {
|
|
|
|
info: SiteInfo {
|
|
|
|
title: "test".to_string(),
|
|
|
|
domain: "test".to_string(),
|
|
|
|
pages: vec![],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
let mut mock_service = MockSiteService::new();
|
|
|
|
mock_service
|
|
|
|
.expect_get_posts()
|
|
|
|
.times(1)
|
|
|
|
.returning(move |_, _, _| {
|
|
|
|
Box::pin(async {
|
|
|
|
Ok(Paginated {
|
|
|
|
data: vec![
|
|
|
|
Post {
|
|
|
|
blocks: vec![Block::Text {
|
|
|
|
text: "Hello, world!".to_string(),
|
|
|
|
}],
|
|
|
|
},
|
|
|
|
Post {
|
|
|
|
blocks: vec![Block::Text {
|
|
|
|
text: "Something else!".to_string(),
|
|
|
|
}],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
next: None,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
server_context().insert(SiteServiceProvider::with(mock_service));
|
|
|
|
|
|
|
|
app.rebuild_in_place();
|
|
|
|
let elem_str = dioxus::ssr::render(&app);
|
|
|
|
println!("elem_str: {elem_str}");
|
|
|
|
assert!(elem_str.contains("Hello, world!"));
|
|
|
|
assert!(elem_str.contains("Something else!"));
|
|
|
|
}
|
|
|
|
}
|