From 098972d0004d81bb1abaac2476e9a923ae2d9570 Mon Sep 17 00:00:00 2001 From: Matthias Lodner Date: Sat, 17 Jan 2026 04:18:20 +0100 Subject: [PATCH] Added functionality to added article. --- Cargo.lock | 16 +++++++ common/Cargo.toml | 1 + common/src/models/article.rs | 27 ++++++++++- common/src/models/origin.rs | 15 ++++-- .../app/components/article/articleCreate.vue | 6 +-- frontend/app/types/origin.ts | 4 +- frontend/nuxt.config.ts | 6 +++ server/Cargo.toml | 1 + server/migrations/20260116005924_init.sql | 48 +++++++++++++++++++ server/src/main.rs | 31 ++++++++++-- 10 files changed, 140 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eebeecc..4078bf2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,6 +399,7 @@ name = "common" version = "0.1.0" dependencies = [ "chrono", + "log", "serde", "serde_json", "sqlx", @@ -1881,6 +1882,7 @@ dependencies = [ "serde_json", "sqlx", "tokio", + "tower-http", "tracing", "tracing-subscriber", ] @@ -2351,6 +2353,20 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags 2.10.0", + "bytes", + "http", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" diff --git a/common/Cargo.toml b/common/Cargo.toml index 83cff9b..3872ffd 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -14,3 +14,4 @@ sqlx = { version = "0.8.6", features = [ "runtime-async-std-native-tls", "postgr # Etc. chrono = { version = "0.4.42", features = [ "serde" ] } +log = "0.4.29" diff --git a/common/src/models/article.rs b/common/src/models/article.rs index 9fd31e4..9c51508 100644 --- a/common/src/models/article.rs +++ b/common/src/models/article.rs @@ -1,7 +1,10 @@ use serde::{Deserialize, Serialize}; -use sqlx::FromRow; +use sqlx::{FromRow, PgPool}; use crate::models::origin::Origin; use crate::models::variant::Variant; +use sqlx::{Arguments, Pool, Row, Postgres, Error}; +use sqlx::postgres::{PgArguments, PgQueryResult, PgRow}; +use log::{debug, info}; #[derive(Debug, Deserialize, Serialize, Clone, FromRow)] pub struct Article { @@ -13,3 +16,25 @@ pub struct Article { pub ingredients: Option, pub variants: Vec, } + +pub async fn insert_article(article: &Article, pool: PgPool) { + let mut args = PgArguments::default(); + args.add(&article.name); + args.add(&article.bio); + args.add(&article.origin); + args.add(&article.description); + args.add(&article.ingredients); + + // Add to price history: + let statement = format!( + "INSERT INTO {} (name, bio, origin, description, ingredients) VALUES ($1, $2, $3, $4, $5)", + "article", + ); + + let res = sqlx::query_with( + statement.as_str(), + args) + .execute(&pool).await.unwrap(); + + info!("{:#?}", res); +} diff --git a/common/src/models/origin.rs b/common/src/models/origin.rs index 83b0b91..939df11 100644 --- a/common/src/models/origin.rs +++ b/common/src/models/origin.rs @@ -6,15 +6,22 @@ use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize, Copy, Clone, PartialEq, sqlx::Type)] pub enum Origin { EU, - NEU, - EUnEU, + NonEU, + EUnonEU, +} +impl Origin { + pub const VEC: &'static [Origin] = &[Origin::EU, Origin::NonEU, Origin::EUnonEU]; + + pub fn position(&self) -> usize { + Origin::VEC.iter().position(|r| *r == *self).unwrap() + } } fn to_string(unit: Origin, f: &mut Formatter) -> fmt::Result { match unit { Origin::EU => write!(f, "EU"), - Origin::NEU => write!(f, "Nicht EU"), - Origin::EUnEU => write!(f, "EU / Nicht EU"), + Origin::NonEU => write!(f, "Nicht EU"), + Origin::EUnonEU => write!(f, "EU / Nicht EU"), } } diff --git a/frontend/app/components/article/articleCreate.vue b/frontend/app/components/article/articleCreate.vue index b58ad7b..e874c41 100644 --- a/frontend/app/components/article/articleCreate.vue +++ b/frontend/app/components/article/articleCreate.vue @@ -17,8 +17,8 @@ let origins: Origin[] = [ Origin.EU, - Origin.NEU, - Origin.EUnEU + Origin.NonEU, + Origin.EUnonEU ]; async function create() { @@ -96,7 +96,7 @@ diff --git a/frontend/app/types/origin.ts b/frontend/app/types/origin.ts index 43766c9..031f747 100644 --- a/frontend/app/types/origin.ts +++ b/frontend/app/types/origin.ts @@ -1,5 +1,5 @@ export enum Origin { EU = "EU", - NEU = "Nicht - EU", - EUnEU= "EU / Nicht EU", + NonEU = "NonEU", + EUnonEU= "EUnonEU", } diff --git a/frontend/nuxt.config.ts b/frontend/nuxt.config.ts index 6d21276..42e7de1 100644 --- a/frontend/nuxt.config.ts +++ b/frontend/nuxt.config.ts @@ -9,6 +9,12 @@ export default defineNuxtConfig({ }, }, + runtimeConfig: { + public: { + url: process.env.URL || 'http://localhost:9090', + }, + }, + compatibilityDate: '2025-07-15', devtools: { enabled: true }, diff --git a/server/Cargo.toml b/server/Cargo.toml index ea99600..8fa1cfa 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -14,6 +14,7 @@ common = {path = "../common"} axum = "0.8.8" tokio = { version = "1.49.0", default-features = false, features = ["full"] } http = "1.4.0" +tower-http = {version = "0.6.8", features = ["cors"]} tracing = "=0.1.44" tracing-subscriber = "0.3.22" diff --git a/server/migrations/20260116005924_init.sql b/server/migrations/20260116005924_init.sql index 8ddc1d3..9bbd795 100644 --- a/server/migrations/20260116005924_init.sql +++ b/server/migrations/20260116005924_init.sql @@ -1 +1,49 @@ -- Add migration script here +CREATE TABLE origin +( + id bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 0 MINVALUE 0 ), + name text NOT NULL, + CONSTRAINT origin_id PRIMARY KEY (id) + INCLUDE(id) +); + +CREATE TABLE article +( + id bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 ), + name text NOT NULL, + bio boolean NOT NULL, + origin bigint NOT NULL, + description text, + ingredients text, + CONSTRAINT article_id PRIMARY KEY (id) + INCLUDE(id), + FOREIGN KEY (origin) + REFERENCES origin (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION + NOT VALID + +); + +CREATE TABLE variant +( + id bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 ), + article_id bigint NOT NULL, + weight text NOT NULL, + ean text NOT NULL, + name text NOT NULL, + description text NOT NULL, + ingredients text NOT NULL, + CONSTRAINT variant_id PRIMARY KEY (id) + INCLUDE(id), + FOREIGN KEY (article_id) + REFERENCES article (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION + NOT VALID +); + +-- Insert origin options +INSERT INTO origin (name) VALUES ('EU'); +INSERT INTO origin (name) VALUES ('Nicht EU'); +INSERT INTO origin (name) VALUES ('EU / Nicht EU'); diff --git a/server/src/main.rs b/server/src/main.rs index 9384e7e..a6fedd5 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -7,9 +7,14 @@ use axum::{ use axum::extract::State; use dotenv::dotenv; use env_logger::fmt::style::Reset; -use common::models::article::Article; +use http::{header, Method}; +use common::models::article::{insert_article, Article}; use common::models::origin::Origin; use sqlx::{ postgres::PgPoolOptions, PgPool }; +use tower_http::cors::{AllowOrigin, Any, CorsLayer}; +use tracing::info; +use http::header::{AUTHORIZATION, ACCEPT, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE, ACCESS_CONTROL_ALLOW_CREDENTIALS}; + #[tokio::main] async fn main() { @@ -23,24 +28,36 @@ async fn main() { // initialize tracing tracing_subscriber::fmt().init(); +/* + tracing_subscriber::fmt() + .with_max_level(tracing::Level::INFO) + .init(); +*/ let pool = PgPoolOptions::new() .max_connections(50) .connect(&database) .await .expect(&format!("Can't connect to database: {}", &database)); + sqlx::migrate!().run(&pool).await.expect("Migrations failed"); + let cors = CorsLayer::new() + .allow_methods([Method::GET, Method::POST]) + .allow_headers([ACCEPT, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE]) + .allow_origin(AllowOrigin::any()); + // build our application with a route let app = Router::new() // `GET /` goes to `root` .route("/", get(root)) - // `POST /users` goes to `create_user` .route("/article", post(create_article)) - .with_state(pool); + .with_state(pool) + .layer(cors); + + let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); + info!("Server started on: {}", &addr); - // run our app with hyper, listening globally on port 3000 - let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); axum::serve(listener, app).await.unwrap(); } @@ -54,6 +71,8 @@ async fn create_article( State(pool): State, Json(payload): Json
, ) -> (StatusCode, Json
) { + info!("Test"); + let article = Article { id: payload.id, name: payload.name, @@ -64,5 +83,7 @@ async fn create_article( variants: payload.variants, }; + insert_article(&article, pool).await; + (StatusCode::CREATED, Json(article)) }