diff options
| author | WriterV2 <primary-v2@protonmail.com> | 2024-11-05 19:06:54 +0100 |
|---|---|---|
| committer | WriterV2 <primary-v2@protonmail.com> | 2024-11-05 19:06:54 +0100 |
| commit | 845073129204835413b53bb40ca7b6a7806d373a (patch) | |
| tree | 32b62478e3cee43eae9472a0ad69e8890e30b6e6 /src | |
| parent | dab09c4e4d1e4b21216b630bb44e57f597dfe85b (diff) | |
Feat: Add card content for story
- Refactoring: Add filepath formatting method
- Add extra error context in story file sync
- Add specific product as parameter to product specific card content
trait method
- TODO: Add pdf icon and epub icon to story card content
- Update tailwind config to look in all .rs files in src/
Diffstat (limited to 'src')
| -rw-r--r-- | src/db/story.rs | 46 | ||||
| -rw-r--r-- | src/handlers/admin.rs | 14 | ||||
| -rw-r--r-- | src/handlers/frontend_builder.rs | 7 |
3 files changed, 38 insertions, 29 deletions
diff --git a/src/db/story.rs b/src/db/story.rs index 0680e94..4228e80 100644 --- a/src/db/story.rs +++ b/src/db/story.rs @@ -2,6 +2,7 @@ use std::ffi::OsStr; use std::fs::{read_dir, remove_file}; use std::io::{BufWriter, Write}; +use anyhow::Context; use axum::async_trait; use maud::html; use sqlx::SqlitePool; @@ -30,25 +31,21 @@ impl ProductMarker for Story { } pub async fn synchronize_story_files(pool: &SqlitePool) -> Result<(), anyhow::Error> { - for entry in read_dir("static")? { - let path = entry?.path(); + for entry in read_dir("static").with_context(|| "Failed to read directory")? { + let path = entry.with_context(|| "Failed to get entry")?.path(); if path.extension().is_some_and(|ext| ext == OsStr::new("pdf") || ext == OsStr::new("epub")) { - remove_file(path)?; + remove_file(path).with_context(|| "Failed to remove file")?; } } let results = sqlx::query!("SELECT p.name, s.pdf, s.epub FROM story s INNER JOIN product p ON s.pid = p.id").fetch_all(pool).await?; for result in results.iter() { - let mut pdf_filename = format!("{}.pdf", result.name).to_lowercase(); - pdf_filename.retain(|c| !c.is_whitespace()); + let pdf_filename = format_filepath(&result.name, "pdf"); + let file = std::fs::File::create_new(&pdf_filename).with_context(|| format!("Failed to create {}", &pdf_filename))?; + BufWriter::new(file).write_all(&result.pdf.to_vec()).with_context(|| format!("Failed to write {}", &pdf_filename))?; - let file = std::fs::File::create_new(format!("static/{}", pdf_filename))?; - BufWriter::new(file).write_all(&result.pdf.to_vec())?; - - let mut epub_filename = format!("{}.epub", result.name).to_lowercase(); - epub_filename.retain(|c| !c.is_whitespace()); - - let file = std::fs::File::create_new(format!("static/{}", epub_filename))?; - BufWriter::new(file).write_all(&result.epub.to_vec())?; + let epub_filename = format_filepath(&result.name, "epub"); + let file = std::fs::File::create_new(&epub_filename).with_context(|| format!("Failed to create {}", &epub_filename))?; + BufWriter::new(file).write_all(&result.epub.to_vec()).with_context(|| format!("Failed to write {}", &epub_filename))?; } Ok(()) } @@ -101,13 +98,26 @@ impl ProductDatabaseHandler for Story { impl PageBuilder for Story { fn page_title() -> String { "Stories".to_string() - } + } - // TODO: Add pdf and epub download link + language info - fn product_specific_card_content(&self) -> maud::Markup { + // TODO: Add pdf and epub icons + fn product_specific_card_content<T: PageBuilder + ProductMarker> + (&self, specific_product: &super::product::SpecificProduct<T>) -> maud::Markup { html!( - span { + div class="flex justify-start mt-5 text-sm" { + span class="mr-10" { (&self.language) } + div class="flex justify-between" { + a href=(format_filepath(&specific_product.product.name, "pdf")) { "PDF" } + a href=(format_filepath(&specific_product.product.name, "epub")) { "EPUB" } + } } - ) + ) } } + +pub fn format_filepath(name: &str, extension: &str) -> String { + let mut filename = format!("static/{}.{}", name, extension).to_lowercase(); + filename.retain(|c| !c.is_whitespace()); + filename +} + diff --git a/src/handlers/admin.rs b/src/handlers/admin.rs index 6cfe133..a48be21 100644 --- a/src/handlers/admin.rs +++ b/src/handlers/admin.rs @@ -11,7 +11,7 @@ use axum::{Extension, Json}; use rand::Rng; use subtle::ConstantTimeEq; -use crate::db::story::Story; +use crate::db::story::{format_filepath, Story}; use crate::db::ProductDatabaseHandler; use crate::error::AppError; @@ -95,10 +95,8 @@ pub async fn upload_story( }; let pdf = if let Some(pdf_value) = form.get("pdf") { - let mut filename = format!("{}.pdf", name).to_lowercase(); - filename.retain(|c| !c.is_whitespace()); - - let file = std::fs::File::create_new(format!("static/{}", filename))?; + let filename = format_filepath(&name, "pdf"); + let file = std::fs::File::create_new(filename)?; BufWriter::new(file).write_all(pdf_value)?; pdf_value.to_vec() } else { @@ -106,10 +104,8 @@ pub async fn upload_story( }; let epub = if let Some(epub_value) = form.get("epub") { - let mut filename = format!("{}.epub", name).to_lowercase(); - filename.retain(|c| !c.is_whitespace()); - - let file = std::fs::File::create_new(format!("static/{}", filename))?; + let filename = format_filepath(&name, "epub"); + let file = std::fs::File::create_new(filename)?; BufWriter::new(file).write_all(epub_value)?; epub_value.to_vec() } else { diff --git a/src/handlers/frontend_builder.rs b/src/handlers/frontend_builder.rs index 4a9ea67..515277e 100644 --- a/src/handlers/frontend_builder.rs +++ b/src/handlers/frontend_builder.rs @@ -75,7 +75,7 @@ fn card<T: PageBuilder + ProductMarker>(specific_product: SpecificProduct<T>) -> (specific_product.product.description) } div { - (specific_product.detail.product_specific_card_content()) + (specific_product.detail.product_specific_card_content(&specific_product)) } div class="flex flex-row space-x-5 mt-9 text-xs" { span {"Upload: " (upload_date)} @@ -114,5 +114,8 @@ pub async fn build_page<T: Sized + ProductMarker + PageBuilder + ProductDatabase pub trait PageBuilder { fn page_title() -> String; - fn product_specific_card_content(&self) -> Markup; + fn product_specific_card_content<T: PageBuilder + ProductMarker>( + &self, + specific_product: &SpecificProduct<T>, + ) -> Markup; } |
