Initial Bard library commit.
This was added to test the database into server context pipeline.
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bard"
|
name = "bard"
|
||||||
version = "0.1.0"
|
version = "0.0.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
description = "Dioxus components that will display a Tavern blogging system Blog."
|
description = "Dioxus components that will display a Tavern blogging system Blog."
|
||||||
repository = "/CyberMages/tavern"
|
repository = "/CyberMages/tavern"
|
||||||
@ -10,3 +10,4 @@ readme = "README.md"
|
|||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
tavern = { version = "0.2.4", path = "../tavern", registry = "cybermages" }
|
||||||
|
|||||||
238
bard/src/components.rs
Normal file
238
bard/src/components.rs
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
use tavern::Lore;
|
||||||
|
|
||||||
|
use crate::components::social::*;
|
||||||
|
use crate::page::Page;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const AUTHOR_CSS: Asset = asset!("/assets/css/blog_author.css");
|
||||||
|
const LIST_CSS: Asset = asset!("/assets/css/blog_list.css");
|
||||||
|
const NAV_CSS: Asset = asset!("/assets/css/blog_nav.css");
|
||||||
|
const POST_CSS: Asset = asset!("/assets/css/blog_post.css");
|
||||||
|
const TAG_CSS: Asset = asset!("/assets/css/blog_tag.css");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
pub enum TagStyle
|
||||||
|
{
|
||||||
|
Regular,
|
||||||
|
Easy,
|
||||||
|
Medium,
|
||||||
|
Hard
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
pub enum Tag
|
||||||
|
{
|
||||||
|
LeetCode,
|
||||||
|
Embedded,
|
||||||
|
Simulation,
|
||||||
|
Web
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn TagItem(tag: Tag, style: TagStyle) -> Element
|
||||||
|
{
|
||||||
|
let text = match tag
|
||||||
|
{
|
||||||
|
Tag::LeetCode => { "LeetCode" }
|
||||||
|
Tag::Embedded => { "Embedded" }
|
||||||
|
Tag::Simulation => { "Simulation" }
|
||||||
|
Tag::Web => { "Web" }
|
||||||
|
};
|
||||||
|
|
||||||
|
let tag_style = match style
|
||||||
|
{
|
||||||
|
TagStyle::Regular => { "none" }
|
||||||
|
TagStyle::Easy => { "easy" }
|
||||||
|
TagStyle::Medium => { "medium" }
|
||||||
|
TagStyle::Hard => { "hard" }
|
||||||
|
};
|
||||||
|
|
||||||
|
rsx!
|
||||||
|
{
|
||||||
|
li
|
||||||
|
{
|
||||||
|
class: "tag_item",
|
||||||
|
a { class: "{tag_style}", "{text}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn TagList(children: Element) -> Element
|
||||||
|
{
|
||||||
|
rsx!
|
||||||
|
{
|
||||||
|
document::Link { rel: "stylesheet", href: TAG_CSS }
|
||||||
|
|
||||||
|
h5
|
||||||
|
{
|
||||||
|
class: "blog_tag_style",
|
||||||
|
ul
|
||||||
|
{
|
||||||
|
class: "tag_list",
|
||||||
|
{children}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn BlogAuthor() -> Element
|
||||||
|
{
|
||||||
|
rsx!
|
||||||
|
{
|
||||||
|
document::Link { rel: "stylesheet", href: AUTHOR_CSS }
|
||||||
|
|
||||||
|
section
|
||||||
|
{
|
||||||
|
class: "blog_author_style",
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn BlogItem(title: String, slug: String, author: String,
|
||||||
|
summary: String, tags: Vec<(Tag, TagStyle)>) -> Element
|
||||||
|
{
|
||||||
|
rsx!
|
||||||
|
{
|
||||||
|
li
|
||||||
|
{
|
||||||
|
class: "blog_item",
|
||||||
|
Link
|
||||||
|
{
|
||||||
|
to: Page::Post { slug: slug },
|
||||||
|
h1 { "{title}" }
|
||||||
|
}
|
||||||
|
TagList
|
||||||
|
{
|
||||||
|
for (tag, style) in tags
|
||||||
|
{
|
||||||
|
TagItem
|
||||||
|
{
|
||||||
|
tag: tag,
|
||||||
|
style: style
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h4 { "Author: {author}" }
|
||||||
|
p { "{summary}" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn BlogList(children: Element) -> Element
|
||||||
|
{
|
||||||
|
rsx!
|
||||||
|
{
|
||||||
|
document::Link { rel: "stylesheet", href: LIST_CSS }
|
||||||
|
|
||||||
|
section
|
||||||
|
{
|
||||||
|
class: "blog_list_style",
|
||||||
|
ul
|
||||||
|
{
|
||||||
|
class: "blog_list",
|
||||||
|
{children}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn BlogNav() -> Element
|
||||||
|
{
|
||||||
|
rsx!
|
||||||
|
{
|
||||||
|
document::Link { rel: "stylesheet", href: NAV_CSS }
|
||||||
|
|
||||||
|
section
|
||||||
|
{
|
||||||
|
class: "blog_nav_style",
|
||||||
|
div
|
||||||
|
{
|
||||||
|
class: "tag_style",
|
||||||
|
h3 { "Categories" }
|
||||||
|
ul
|
||||||
|
{
|
||||||
|
class: "tag_list",
|
||||||
|
li
|
||||||
|
{
|
||||||
|
class: "tag_item",
|
||||||
|
a { href: "/blog.html", "LeetCode" }
|
||||||
|
}
|
||||||
|
li
|
||||||
|
{
|
||||||
|
class: "tag_item",
|
||||||
|
a { href: "/blog.html", "Embedded" }
|
||||||
|
}
|
||||||
|
li
|
||||||
|
{
|
||||||
|
class: "tag_item",
|
||||||
|
a { href: "/blog.html", "Simulation" }
|
||||||
|
}
|
||||||
|
li
|
||||||
|
{
|
||||||
|
class: "tag_item",
|
||||||
|
a { href: "/blog.html", "Web" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SocialButtonList
|
||||||
|
{
|
||||||
|
SocialButton
|
||||||
|
{
|
||||||
|
link: String::from("https://www.linkedin.com/company/cybermages-llc"),
|
||||||
|
company: Company::LinkedIn,
|
||||||
|
size: Size::Small
|
||||||
|
}
|
||||||
|
SocialButton
|
||||||
|
{
|
||||||
|
link: String::from("https://bsky.app/profile/cybermages.tech"),
|
||||||
|
company: Company::Bluesky,
|
||||||
|
size: Size::Small
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn BlogPost(children: Element) -> Element
|
||||||
|
{
|
||||||
|
rsx!
|
||||||
|
{
|
||||||
|
document::Link { rel: "stylesheet", href: POST_CSS }
|
||||||
|
|
||||||
|
article
|
||||||
|
{
|
||||||
|
class: "blog_post_style",
|
||||||
|
h1 { "Leet Code: Let's Get Started" }
|
||||||
|
TagList
|
||||||
|
{
|
||||||
|
TagItem
|
||||||
|
{
|
||||||
|
tag: Tag::LeetCode,
|
||||||
|
style: TagStyle::Regular
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h4 { "Author: ", a { href: "https://cybermages.tech", "Jason Smith" } }
|
||||||
|
{children}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,4 +4,16 @@ mod info;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
use tavern::Database;
|
||||||
|
|
||||||
pub use crate::info::{get_name, get_version};
|
pub use crate::info::{get_name, get_version};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn init_database<P>(path: P)
|
||||||
|
-> Result<std::sync::Arc<Database>, Box<dyn std::error::Error>>
|
||||||
|
where P: AsRef<std::path::Path>
|
||||||
|
{
|
||||||
|
let db = Database::open(path).await?;
|
||||||
|
Ok(std::sync::Arc::new(db))
|
||||||
|
}
|
||||||
|
|||||||
27
bard/src/server.rs
Normal file
27
bard/src/server.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use dioxus::prelude::*;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use crate::{Database, Lore, Tale};
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn get_blog_list() -> Result<Vec<Lore>, ServerFnError> {
|
||||||
|
let db = server_context()
|
||||||
|
.get::<Arc<Database>>()
|
||||||
|
.ok_or_else(|| ServerFnError::ServerError("Database context not available".to_string()))?;
|
||||||
|
|
||||||
|
let summaries = db.get_tales_summary(&[]).await
|
||||||
|
.map_err(|e| ServerFnError::ServerError(e.to_string()))?;
|
||||||
|
|
||||||
|
Ok(summaries)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn get_blog_post(slug: String) -> Result<Tale, ServerFnError> {
|
||||||
|
let db = server_context()
|
||||||
|
.get::<Arc<Database>>()
|
||||||
|
.ok_or_else(|| ServerFnError::ServerError("Database context not available".to_string()))?;
|
||||||
|
|
||||||
|
let tale = db.get_tale_by_slug(&slug).await
|
||||||
|
.map_err(|e| ServerFnError::ServerError(e.to_string()))?;
|
||||||
|
|
||||||
|
tale.ok_or(ServerFnError::ServerError("Post not found".into()))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user