summaryrefslogtreecommitdiff
path: root/src/db/story.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/db/story.rs')
-rw-r--r--src/db/story.rs129
1 files changed, 0 insertions, 129 deletions
diff --git a/src/db/story.rs b/src/db/story.rs
deleted file mode 100644
index 1566d22..0000000
--- a/src/db/story.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-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;
-
-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,
- pub language: String,
- pub pdf: Vec<u8>,
- pub pid: i64,
-}
-
-impl ProductMarker for Story {
- fn product_id(&self) -> i64 {
- self.pid
- }
-}
-
-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")) {
- remove_file(path).with_context(|| "Failed to remove file")?;
- }
- }
- let results =
- sqlx::query!("SELECT p.name, s.pdf 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))?;
- }
- Ok(())
-}
-
-#[async_trait]
-impl ProductDatabaseHandler for Story {
- async fn get_all(pool: &SqlitePool) -> Result<Vec<Self>, AppError>
- where
- Self: Sized,
- {
- Ok(sqlx::query_as!(Story, "SELECT * FROM story")
- .fetch_all(pool)
- .await?)
- }
-
- async fn post(
- &self,
- pool: &SqlitePool,
- name: &str,
- description: &str,
- tags: Vec<&str>,
- ) -> Result<Self, AppError>
- where
- Self: Sized,
- {
- let mut tx = pool.begin().await?;
- let product = Product::post(&mut tx, name, description, tags).await?;
- let story = sqlx::query_as!(
- Story,
- "INSERT INTO story (language, pdf, pid) VALUES ($1, $2, $3) RETURNING id, language, pdf, pid",
- self.language,
- self.pdf,
- product.id)
- .fetch_one(&mut *tx)
- .await?;
-
- tx.commit().await?;
-
- Ok(story)
- }
-
- async fn delete(pool: &SqlitePool, pid: i64) -> Result<(), AppError>
- where
- Self: Sized,
- {
- let mut tx = pool.begin().await?;
- sqlx::query!("DELETE FROM story WHERE pid = $1", pid)
- .execute(&mut *tx)
- .await?;
- Product::delete(&mut tx, pid).await?;
- tx.commit().await?;
- Ok(())
- }
-}
-
-impl<'a> PageBuilder<'a> for Story {
- fn page_title() -> &'a str {
- "Stories"
- }
-
- // TODO: Add pdf icon
- fn product_specific_card_content<T: PageBuilder<'a> + 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" {
- a href=(format_filepath(&specific_product.product.name, "pdf")) { "PDF" }
- }
- }
- )
- }
-}
-
-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
-}