Initial Bard library commit.

This was added to test the database into server context pipeline.
This commit is contained in:
2025-09-02 14:00:19 -04:00
parent 3fc6bf0666
commit 877d7e15a3
4 changed files with 279 additions and 1 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "bard"
version = "0.1.0"
version = "0.0.1"
edition = "2024"
description = "Dioxus components that will display a Tavern blogging system Blog."
repository = "/CyberMages/tavern"
@ -10,3 +10,4 @@ readme = "README.md"
license = "Apache-2.0"
[dependencies]
tavern = { version = "0.2.4", path = "../tavern", registry = "cybermages" }

238
bard/src/components.rs Normal file
View 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}
}
}
}

View File

@ -4,4 +4,16 @@ mod info;
use tavern::Database;
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
View 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()))
}