From 5a021f978164648650a134c48d51321d66c91d38 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Sun, 4 Aug 2024 17:35:16 +0200 Subject: [PATCH 1/4] move doctype into head --- src/common.rs | 3 ++- src/main.rs | 8 +------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/common.rs b/src/common.rs index 1934d39..111c07a 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,9 +1,10 @@ use axum::response::IntoResponse; -use maud::{html, Markup}; +use maud::{html, Markup, DOCTYPE}; use stylist::{css, GlobalStyle}; pub fn head(title: &str) -> Markup { html!( + (DOCTYPE) head { title { "Recueil " (title) } link rel = "stylesheet" href = "/style.css"; diff --git a/src/main.rs b/src/main.rs index 6d76178..2fd083d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ use axum::{ }; use chrono::prelude::*; use common::{footer, head, header, style}; -use maud::{html, Escaper, Markup, PreEscaped, DOCTYPE}; +use maud::{html, Escaper, Markup, PreEscaped}; use serde::{Deserialize, Serialize}; use store::Store; use tokio::net::TcpListener; @@ -51,7 +51,6 @@ async fn main() -> Result<()> { async fn home() -> Markup { html!( - (DOCTYPE) (head("")) body { content { @@ -73,7 +72,6 @@ async fn home() -> Markup { async fn topics(State(state): State) -> impl IntoResponse { let topics = state.store.read().unwrap().list().unwrap(); html!( - (DOCTYPE) (head("sujets")) body { content { @@ -97,7 +95,6 @@ async fn topics(State(state): State) -> impl IntoResponse { async fn activity(State(state): State) -> impl IntoResponse { let topics = state.store.read().unwrap().activity().unwrap(); html!( - (DOCTYPE) (head("activité")) body { content { @@ -124,7 +121,6 @@ async fn topic(Path(name): Path, State(state): State) -> impl }; html!( - (DOCTYPE) (head(&name)) body { content { @@ -218,7 +214,6 @@ fn sanithize_identifier(input: &str) -> String { async fn create() -> impl IntoResponse { html!( - (DOCTYPE) (head("créer")) body { content { @@ -251,7 +246,6 @@ async fn create() -> impl IntoResponse { fn error(message: impl ToString) -> Markup { let message = message.to_string(); html!( - (DOCTYPE) (head("Failure")) body { content { From a07c61fdbfddcbb3f1c4a8dfd49b6efa2a79fa27 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Sun, 4 Aug 2024 17:53:25 +0200 Subject: [PATCH 2/4] parametrize port, address and store path --- src/main.rs | 27 +++++++++++++++++++++++++-- src/store.rs | 12 +++++------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2fd083d..0bd4169 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use std::{ fmt::Write, + path::PathBuf, sync::{Arc, RwLock}, }; @@ -22,6 +23,22 @@ use validator::{Validate, ValidationError}; mod common; mod store; +#[derive(Debug, clap::Parser)] +/// Arbre +struct Cmd { + #[arg(short, long, default_value_t = 8200)] + /// Port on which th server will listen. + port: u16, + + #[arg(short, long, default_value = "0.0.0.0")] + /// Hostname or address on which th server will listen. + address: String, + + #[arg(short, long, default_value = "./store")] + /// Path to the directory to use as storage for topics. + store: PathBuf, +} + #[derive(Debug, Clone)] struct MainState { store: Arc>, @@ -29,7 +46,13 @@ struct MainState { #[tokio::main] async fn main() -> Result<()> { - let store = Store::open("./store")?; + let Cmd { + address, + port, + store, + } = clap::Parser::parse(); + + let store = Store::open(store)?; let store = Arc::new(RwLock::new(store)); let state = MainState { store }; @@ -42,7 +65,7 @@ async fn main() -> Result<()> { .route("/", get(home)) .with_state(state); - let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap(); + let listener = TcpListener::bind((address, port)).await.unwrap(); let server = axum::serve(listener, app); server.await?; diff --git a/src/store.rs b/src/store.rs index e86291d..76f1692 100644 --- a/src/store.rs +++ b/src/store.rs @@ -1,18 +1,18 @@ use std::{ fs::{self, OpenOptions}, io::{ErrorKind, Write}, + path::PathBuf, }; use anyhow::Result; #[derive(Debug)] pub struct Store { - path: String, + path: PathBuf, } impl Store { - pub fn open(path: impl ToString) -> Result { - let path = path.to_string(); + pub fn open(path: PathBuf) -> Result { fs::create_dir_all(&path)?; Ok(Self { path }) } @@ -44,8 +44,7 @@ impl Store { } pub fn get(&self, topic: &str) -> Result> { - let base = &self.path; - let path = format!("{base}/{topic}"); + let path = self.path.join(topic); let content = fs::read_to_string(path)?; Ok(content.split(SEPARATOR).map(String::from).collect()) } @@ -53,8 +52,7 @@ impl Store { pub fn insert(&mut self, topic: &str, content: String) -> Result<()> { let content = content.replace('\u{c}', " "); let content = content.trim(); - let base = &self.path; - let path = format!("{base}/{topic}"); + let path = self.path.join(topic); match OpenOptions::new().append(true).create(false).open(&path) { Ok(mut file) => write!(&mut file, "{SEPARATOR}\n{content}\n")?, Err(error) if error.kind() == ErrorKind::NotFound => drop(fs::write(path, content)), From b039753181d5c38123a05ab93ec522d65e90c776 Mon Sep 17 00:00:00 2001 From: JOLIMAITRE Matthieu Date: Sun, 4 Aug 2024 18:19:29 +0200 Subject: [PATCH 3/4] log params, better create form display, refactor --- src/common.rs | 11 +++++++++++ src/main.rs | 10 ++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/common.rs b/src/common.rs index 111c07a..c791dab 100644 --- a/src/common.rs +++ b/src/common.rs @@ -72,6 +72,17 @@ pub async fn style() -> impl IntoResponse { color: wheat; } + label { + display: inline-block; + width: 8rem; + } + + textarea { + width: 100%; + height: 5rem; + box-sizing: border-box; + } + main { padding: 2rem; } diff --git a/src/main.rs b/src/main.rs index 0bd4169..690e9e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,8 +65,10 @@ async fn main() -> Result<()> { .route("/", get(home)) .with_state(state); - let listener = TcpListener::bind((address, port)).await.unwrap(); + let listener = TcpListener::bind((address.as_str(), port)).await.unwrap(); let server = axum::serve(listener, app); + + println!("Listening on http://{address}:{port}"); server.await?; Ok(()) @@ -183,11 +185,11 @@ fn validate_topic(topic: &str) -> Result<(), ValidationError> { Ok(()) } -async fn post(State(state): State, Form(post_content): Form) -> Response { +async fn post(State(state): State, Form(post): Form) -> Response { let mut store = state.store.write().unwrap(); let date = Utc::now().format("%d/%m/%Y"); - if post_content.validate().is_err() { + if post.validate().is_err() { return (StatusCode::BAD_REQUEST, "Bad input.").into_response(); } @@ -195,7 +197,7 @@ async fn post(State(state): State, Form(post_content): Form Date: Sun, 4 Aug 2024 18:20:10 +0200 Subject: [PATCH 4/4] add watch script --- watch | 3 +++ 1 file changed, 3 insertions(+) create mode 100755 watch diff --git a/watch b/watch new file mode 100755 index 0000000..ca4c48f --- /dev/null +++ b/watch @@ -0,0 +1,3 @@ +#!/bin/sh + +cargo watch --clear --exec "run -- --address=localhost --port=8080"