From f491ed95a3bc82c31c70b0f38ed841408576ec0c Mon Sep 17 00:00:00 2001 From: WriterV2 Date: Sat, 21 Mar 2026 11:56:19 +0100 Subject: Purge + prepare for local website builder --- src/db/game.rs | 14 ------ src/db/mod.rs | 32 ------------- src/db/product.rs | 110 ------------------------------------------- src/db/producttag.rs | 5 -- src/db/story.rs | 129 --------------------------------------------------- src/db/tag.rs | 5 -- src/db/tool.rs | 14 ------ 7 files changed, 309 deletions(-) delete mode 100644 src/db/game.rs delete mode 100644 src/db/mod.rs delete mode 100644 src/db/product.rs delete mode 100644 src/db/producttag.rs delete mode 100644 src/db/story.rs delete mode 100644 src/db/tag.rs delete mode 100644 src/db/tool.rs (limited to 'src/db') diff --git a/src/db/game.rs b/src/db/game.rs deleted file mode 100644 index e10006c..0000000 --- a/src/db/game.rs +++ /dev/null @@ -1,14 +0,0 @@ -use super::product::ProductMarker; - -#[derive(Debug, serde::Serialize, sqlx::FromRow)] -pub struct Game { - pub id: i64, - pub repolink: String, - pub pid: i64, -} - -impl ProductMarker for Game { - fn product_id(&self) -> i64 { - self.pid - } -} diff --git a/src/db/mod.rs b/src/db/mod.rs deleted file mode 100644 index f1baf44..0000000 --- a/src/db/mod.rs +++ /dev/null @@ -1,32 +0,0 @@ -use sqlx::SqlitePool; - -use crate::error::AppError; -use async_trait::async_trait; - -pub mod game; -pub mod product; -pub mod producttag; -pub mod story; -pub mod tag; -pub mod tool; - -#[async_trait] -pub trait ProductDatabaseHandler { - async fn get_all(pool: &SqlitePool) -> Result, AppError> - where - Self: Sized; - - async fn post( - &self, - pool: &SqlitePool, - name: &str, - description: &str, - tags: Vec<&str>, - ) -> Result - where - Self: Sized; - - async fn delete(pool: &SqlitePool, id: i64) -> Result<(), AppError> - where - Self: Sized; -} diff --git a/src/db/product.rs b/src/db/product.rs deleted file mode 100644 index e5e797f..0000000 --- a/src/db/product.rs +++ /dev/null @@ -1,110 +0,0 @@ -use std::collections::HashMap; -use std::time::SystemTime; - -use sqlx::{QueryBuilder, Sqlite, SqlitePool, Transaction}; - -use crate::error::AppError; - -use super::tag::Tag; -use super::ProductDatabaseHandler; - -#[derive(Debug, serde::Serialize, sqlx::FromRow)] -pub struct Product { - pub id: i64, - pub name: String, - pub description: String, - pub uploaddate: i64, - pub updatedate: i64, -} - -impl Product { - pub async fn post(tx: &mut Transaction<'static, Sqlite>, name: &str, description: &str, tags: Vec<&str>) -> Result { - 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?; - - if !tags.is_empty() { - // insert tags that do not exist yet - let mut tags_query_builder: QueryBuilder = QueryBuilder::new("INSERT INTO tag (name) "); - tags_query_builder.push_values(tags.iter(), | mut b, tag | { b.push_bind(tag); }); - tags_query_builder.push(" ON CONFLICT(name) DO NOTHING;"); - tags_query_builder.build().execute(&mut **tx).await?; - - // fetch all tags of story - let added_tags: Vec = { - let mut tags_fetch_query_builder = QueryBuilder::new("WITH input(name) AS ("); - tags_fetch_query_builder.push_values(tags.iter(), |mut b, tag| { - b.push_bind(tag); - }); - tags_fetch_query_builder.push( - ") \ - SELECT t.id, t.name \ - FROM tag t \ - JOIN input i ON i.name = t.name;" - ); - tags_fetch_query_builder.build_query_as::().fetch_all(&mut **tx).await? - }; - println!("{:?}", added_tags); - - // bind tags to story if they are not bound yet - let mut producttags_query_builder: QueryBuilder = QueryBuilder::new("INSERT INTO producttag (pid, tid) "); - producttags_query_builder.push_values(added_tags.iter(), | mut b, added_tag | { - b.push_bind(product.id).push_bind(added_tag.id); - }); - producttags_query_builder.push(" ON CONFLICT(pid, tid) DO NOTHING;"); - producttags_query_builder - .build().execute(&mut **tx).await?; - - } - Ok(product) - } - - pub async fn delete(tx: &mut Transaction<'static, Sqlite>, pid: i64) -> Result<(), AppError> { - sqlx::query!("DELETE FROM producttag WHERE pid = $1", pid).execute(&mut **tx).await?; - sqlx::query!("DELETE FROM product WHERE id = $1", pid).execute(&mut **tx).await?; - Ok(()) - } -} - -pub trait ProductMarker { - fn product_id(&self) -> i64; -} - -pub struct SpecificProduct { - pub product: Product, - pub detail: T, -} - -pub async fn get_all_products(pool: &SqlitePool) -> Result, AppError> { - Ok(sqlx::query_as!(Product, "SELECT * FROM product") - .fetch_all(pool) - .await?) -} - -pub async fn get_all_specificproducts( - pool: &SqlitePool, -) -> Result>, AppError> { - let product_details = T::get_all(pool).await?; - let products = get_all_products(pool).await?; - let mut details_map: HashMap = product_details - .into_iter() - .map(|detail| (detail.product_id(), detail)) - .collect(); - - let specific_products = products - .into_iter() - .filter_map(|product| { - details_map - .remove(&product.id) - .map(|detail| SpecificProduct { product, detail }) - }) - .collect(); - Ok(specific_products) -} diff --git a/src/db/producttag.rs b/src/db/producttag.rs deleted file mode 100644 index 160e720..0000000 --- a/src/db/producttag.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[derive(Debug, serde::Serialize, sqlx::FromRow)] -pub struct ProductTag { - pub pid: i64, - pub tid: i64, -} 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, - 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, 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 - 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 + ProductMarker>( - &self, - specific_product: &super::product::SpecificProduct, - ) -> 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 -} diff --git a/src/db/tag.rs b/src/db/tag.rs deleted file mode 100644 index df55a8a..0000000 --- a/src/db/tag.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[derive(Debug, serde::Serialize, sqlx::FromRow)] -pub struct Tag { - pub id: i64, - pub name: String, -} diff --git a/src/db/tool.rs b/src/db/tool.rs deleted file mode 100644 index c53dc1e..0000000 --- a/src/db/tool.rs +++ /dev/null @@ -1,14 +0,0 @@ -use super::product::ProductMarker; - -#[derive(Debug, serde::Serialize, sqlx::FromRow)] -pub struct Tool { - pub id: i64, - pub repolink: String, - pub pid: i64, -} - -impl ProductMarker for Tool { - fn product_id(&self) -> i64 { - self.id - } -} -- cgit v1.2.3