summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/db/product.rs19
-rw-r--r--src/db/story.rs66
2 files changed, 54 insertions, 31 deletions
diff --git a/src/db/product.rs b/src/db/product.rs
index 0fc8f05..5b58560 100644
--- a/src/db/product.rs
+++ b/src/db/product.rs
@@ -1,6 +1,7 @@
use std::collections::HashMap;
+use std::time::SystemTime;
-use sqlx::SqlitePool;
+use sqlx::{Sqlite, SqlitePool, Transaction};
use crate::error::AppError;
@@ -15,6 +16,22 @@ pub struct Product {
pub updatedate: i64,
}
+impl Product {
+ pub async fn post(tx: &mut Transaction<'static, Sqlite>, name: String, description: String) -> Result<Product, AppError> {
+ let now = SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_millis() as i64;
+ let product = sqlx::query_as!(
+ Product,
+ "INSERT INTO product (name, description, uploaddate, updatedate) VALUES ($1, $2, $3, $4) RETURNING id, name, description, uploaddate, updatedate",
+ name,
+ description,
+ now,
+ now)
+ .fetch_one(&mut **tx)
+ .await?;
+ Ok(product)
+ }
+}
+
pub trait ProductMarker {
fn product_id(&self) -> i64;
}
diff --git a/src/db/story.rs b/src/db/story.rs
index 4228e80..b77d7a3 100644
--- a/src/db/story.rs
+++ b/src/db/story.rs
@@ -7,14 +7,13 @@ use axum::async_trait;
use maud::html;
use sqlx::SqlitePool;
-use crate::error::AppError;
use crate::db::product::Product;
+use crate::error::AppError;
use crate::handlers::frontend_builder::PageBuilder;
use super::product::ProductMarker;
use super::ProductDatabaseHandler;
-
#[derive(Debug, serde::Serialize, sqlx::FromRow)]
pub struct Story {
pub id: i64,
@@ -33,19 +32,32 @@ impl ProductMarker for Story {
pub async fn synchronize_story_files(pool: &SqlitePool) -> Result<(), anyhow::Error> {
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")) {
+ if path
+ .extension()
+ .is_some_and(|ext| ext == OsStr::new("pdf") || ext == OsStr::new("epub"))
+ {
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?;
+ 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 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(&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 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))?;
+ 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(())
}
@@ -61,24 +73,17 @@ impl ProductDatabaseHandler for Story {
.await?)
}
- async fn post(&self, pool: &SqlitePool, name: String, description: String) -> Result<Self, AppError>
+ async fn post(
+ &self,
+ pool: &SqlitePool,
+ name: String,
+ description: String,
+ ) -> Result<Self, AppError>
where
Self: Sized,
{
- let time = std::time::SystemTime::now();
- let uploaddate = time.duration_since(std::time::UNIX_EPOCH)?.as_millis() as i64;
-
let mut tx = pool.begin().await?;
- let product = sqlx::query_as!(
- Product,
- "INSERT INTO product (name, description, uploaddate, updatedate) VALUES ($1, $2, $3, $4) RETURNING id, name, description, uploaddate, updatedate",
- name,
- description,
- uploaddate,
- uploaddate)
- .fetch_one(&mut *tx)
- .await?;
-
+ let product = Product::post(&mut tx, name, description).await?;
let story = sqlx::query_as!(
Story,
"INSERT INTO story (language, pdf, epub, pid) VALUES ($1, $2, $3, $4) RETURNING id, language, pdf, epub, pid",
@@ -96,14 +101,16 @@ impl ProductDatabaseHandler for Story {
}
impl PageBuilder for Story {
- fn page_title() -> String {
+ fn page_title() -> String {
"Stories".to_string()
- }
+ }
- // TODO: Add pdf and epub icons
- fn product_specific_card_content<T: PageBuilder + ProductMarker>
- (&self, specific_product: &super::product::SpecificProduct<T>) -> maud::Markup {
- html!(
+ // TODO: Add pdf and epub icons
+ fn product_specific_card_content<T: PageBuilder + ProductMarker>(
+ &self,
+ specific_product: &super::product::SpecificProduct<T>,
+ ) -> maud::Markup {
+ html!(
div class="flex justify-start mt-5 text-sm" {
span class="mr-10" { (&self.language) }
div class="flex justify-between" {
@@ -112,7 +119,7 @@ impl PageBuilder for Story {
}
}
)
- }
+ }
}
pub fn format_filepath(name: &str, extension: &str) -> String {
@@ -120,4 +127,3 @@ pub fn format_filepath(name: &str, extension: &str) -> String {
filename.retain(|c| !c.is_whitespace());
filename
}
-