summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWriterV2 <primary-v2@protonmail.com>2024-11-05 19:06:54 +0100
committerWriterV2 <primary-v2@protonmail.com>2024-11-05 19:06:54 +0100
commit845073129204835413b53bb40ca7b6a7806d373a (patch)
tree32b62478e3cee43eae9472a0ad69e8890e30b6e6 /src
parentdab09c4e4d1e4b21216b630bb44e57f597dfe85b (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.rs46
-rw-r--r--src/handlers/admin.rs14
-rw-r--r--src/handlers/frontend_builder.rs7
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;
}